Skip to main content

Scan for Global Entry / NEXUS appointment slots and get notified

Project description

Global Entry Appointment Scanner

Scan for open Global Entry / NEXUS appointment slots and get notified the moment one appears.

CI PyPI Python

demo

Install

Recommended — pipx (installs CLI tools in isolated environments, no conflicts):

brew install pipx        # macOS
pipx install global-entry-scanner           # core (email only)
pipx install "global-entry-scanner[slack]"  # + Slack
pipx install "global-entry-scanner[discord]"# + Discord
pipx install "global-entry-scanner[sms]"    # + Twilio SMS
pipx install "global-entry-scanner[mcp]"    # + MCP server for AI agents
pipx install "global-entry-scanner[all]"    # everything

On macOS, avoid using the system pip3 — it points to Python 3.9 which is too old, and Homebrew's Python will block system-wide installs. pipx handles all of this automatically.

Alternative — pip (if you're inside a virtual environment):

pip install global-entry-scanner
pip install "global-entry-scanner[all]"

Quick start

# 1. Interactive setup — pick locations and configure notifications
global-entry-scanner setup

# 2. Run the scanner
global-entry-scanner scan

CLI

global-entry-scanner locations                                    # list all enrollment centers
global-entry-scanner setup                                        # interactive config wizard
global-entry-scanner scan                                         # run with saved config
global-entry-scanner scan --locations "Chicago, Dallas"           # override locations
global-entry-scanner scan --notify email,slack                    # override channels
global-entry-scanner mcp                                          # start MCP server

Config is saved to ~/.config/global-entry-scanner/config.toml.

Python API

from global_entry_scanner import Scanner
from global_entry_scanner.notifications import SlackNotifier, DiscordNotifier, EmailNotifier

scanner = Scanner(location_ids=[5001, 5140])
scanner.add_notifier(SlackNotifier(webhook_url="https://hooks.slack.com/..."))
scanner.add_notifier(DiscordNotifier(webhook_url="https://discord.com/api/webhooks/..."))
scanner.add_notifier(EmailNotifier(from_email="you@gmail.com", to_email="you@gmail.com", password="app-password"))
scanner.start()  # blocking; Ctrl+C to stop

Scanner options:

Parameter Default Description
location_ids required List of enrollment center IDs
check_interval 900 Seconds between polls (no errors)
error_interval 60 Seconds between polls (on error)
limit 5 Max appointments to fetch per location

Notification channels

Channel Extra Credentials
Email (core) Gmail address + app password
Discord [discord] Webhook URL
Slack [slack] Webhook URL
SMS [sms] Twilio account SID, auth token, phone numbers

All configured channels fire concurrently. One failing channel does not block the others.

Discord webhook setup

  1. Open your Discord server → go to the channel you want notifications in
  2. Click Edit Channel (gear icon) → IntegrationsWebhooksNew Webhook
  3. Give it a name, optionally set an avatar, then click Copy Webhook URL
  4. Paste the URL into setup when prompted, or add it to your config:
[notifications.discord]
webhook_url = "https://discord.com/api/webhooks/1234567890/xxxx"

Twilio SMS setup

  1. Sign up at twilio.com (free trial includes a small credit)
  2. From the Twilio Console dashboard, copy your Account SID and Auth Token
  3. Go to Phone NumbersManageBuy a number to get a Twilio number to send from (free trial includes one)
  4. Add the credentials to your config:
[notifications.sms]
account_sid = "ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
auth_token  = "your_auth_token"
from_number = "+12125550000"   # your Twilio number
to_number   = "+12125551234"   # number to notify

Free trial note: Twilio trial accounts can only send SMS to verified numbers. Go to Phone NumbersManageVerified Caller IDs to add your personal number.

Slack webhook setup

  1. Go to api.slack.com/appsCreate New AppFrom scratch
  2. Under Add features and functionality, choose Incoming Webhooks → toggle it on
  3. Click Add New Webhook to Workspace, pick a channel, and click Allow
  4. Copy the webhook URL that appears, then paste it into setup when prompted or add it to your config:
[notifications.slack]
webhook_url = "https://hooks.slack.com/services/T00000000/B00000000/xxxx"

Claude Code skill

This repo ships a skill for Claude Code that lets you ask Claude directly about slot availability, set up monitoring, and configure notifications — without remembering any commands.

Install the skill

Option 1: From this repo (available now)

In Claude Code, run:

/plugin marketplace add JaiminBrahmbhatt/Global-Entry-Appointment-Scanner
/plugin install global-entry-scanner@global-entry-scanner

Option 2: Official Anthropic marketplace (pending review)

/plugin install global-entry-scanner

What you can ask Claude

Once installed, just talk to Claude naturally:

  • "Are there any open Global Entry slots near Chicago or Dallas?"
  • "Set this up to text me whenever a slot opens at JFK or Newark"
  • "How do I hook up the MCP server to Claude Desktop?"
  • "Run the scanner in the background and notify me on Discord"

Claude will detect whether the MCP server is running and use it directly, or fall back to guiding you through the CLI.


MCP server

Install with pip install global-entry-scanner[mcp], then run global-entry-scanner mcp.

Exposes six tools to AI agents: get_locations, search_locations, check_appointments, start_scan, stop_scan, get_scan_status.

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "global-entry-scanner": {
      "command": "global-entry-scanner",
      "args": ["mcp"]
    }
  }
}

Configuration file

~/.config/global-entry-scanner/config.toml

[scanner]
check_interval = 900
error_interval = 60
limit = 5

[locations]
ids = [5001, 5140]

[notifications.discord]
webhook_url = "https://discord.com/api/webhooks/..."

[notifications.slack]
webhook_url = "https://hooks.slack.com/..."

[notifications.email]
from_email = "you@gmail.com"
to_email = "you@gmail.com"
password = "app-password"

[notifications.sms]
account_sid = "..."
auth_token = "..."
to_number = "+12125551234"
from_number = "+12125550000"

Development

git clone https://github.com/JaiminBrahmbhatt/Global-Entry-Appointment-Scanner
cd Global-Entry-Appointment-Scanner
pip install -e ".[all,dev]"

# Run tests
pytest

# Run live API tests
pytest -m integration

# Lint + type check
ruff check .
mypy global_entry_scanner/

Credits

Inspired by:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

global_entry_scanner-0.1.5.tar.gz (419.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

global_entry_scanner-0.1.5-py3-none-any.whl (16.7 kB view details)

Uploaded Python 3

File details

Details for the file global_entry_scanner-0.1.5.tar.gz.

File metadata

  • Download URL: global_entry_scanner-0.1.5.tar.gz
  • Upload date:
  • Size: 419.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for global_entry_scanner-0.1.5.tar.gz
Algorithm Hash digest
SHA256 792c4552c6d3685b7119b3cab5ead662028bd54e7f9a8da1c464c0e5bc02f242
MD5 d73aaffd4acf3ddb3776302a39274ac4
BLAKE2b-256 742f40d69a4ad58f7d03cfab005e0337630cdda4ba06bfd4477df964ab5f7c82

See more details on using hashes here.

Provenance

The following attestation bundles were made for global_entry_scanner-0.1.5.tar.gz:

Publisher: publish.yml on JaiminBrahmbhatt/Global-Entry-Appointment-Scanner

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file global_entry_scanner-0.1.5-py3-none-any.whl.

File metadata

File hashes

Hashes for global_entry_scanner-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 ee3b67dd73b124459fe2253bd38e84bdd9b9e1ddf37aad4921c6e5ad28f8ed91
MD5 9314c79b0edfcb43b4ad59fda6fa6307
BLAKE2b-256 6fb080ffd397a4d19f6b6b7c389c37679bcd44ac894a03a904814e599f9f7851

See more details on using hashes here.

Provenance

The following attestation bundles were made for global_entry_scanner-0.1.5-py3-none-any.whl:

Publisher: publish.yml on JaiminBrahmbhatt/Global-Entry-Appointment-Scanner

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page