Skip to main content

United MileagePlus award flight search CLI

Project description

Searchaero

Award flight search for Claude Code. Scrapes United MileagePlus award pricing, stores results in a local SQLite database, and exposes a /flights skill that teaches Claude the full workflow — scrape, handle MFA, query, alert, watch.

Scope

  • Airline: United MileagePlus only
  • Routes: Any origin/destination United serves
  • Coverage: Full 337-day booking window, economy/business/first
  • Not supported: Partner awards, cash fares

Quick start

Open Claude Code and paste this. Claude does the rest.

Install searchaero: run uv tool install searchaero to install the CLI, then run searchaero setup to configure credentials and verify Playwright. After setup, ask me to find cheap flights.

Requirements: Claude Code, Python 3.13+, uv

That's it. The /flights skill ships with this repo — when you clone it, Claude already knows how to use searchaero.

Manual install (without Claude)

1. Install

uv tool install searchaero

Why uv? One dependency (bezier) doesn't ship Python 3.13 wheels yet. uv handles the source build automatically; regular pip fails without workarounds.

Or install from source:

git clone https://github.com/JadedOut/searchaero.git
cd searchaero
uv tool install .

2. Set up credentials

searchaero setup

Creates the database, checks Playwright, and prompts for your MileagePlus number and password. Just your MP number and password — no API keys needed. If all three checks show green, you're ready.

Heads up: United requires verification on your first login. When you trigger your first scrape, you'll be prompted for a code. This is a one-time step per browser session.

3. Ask Claude

In Claude Code, just ask:

What's the cheapest flight from Toronto to LA next month?

Or invoke the skill directly with /flights.

See it work

You:    What's the cheapest business class from Toronto to London next month?

Claude: Checking cached data... no results for YYZ-LHR.
        Starting a fresh scrape — this takes about 2 minutes.
        [MFA code requested — enter the 6-digit code from your phone]

        ┌──────────┬──────────┬─────────┬──────────┐
        │ Date     │ Cabin    │ Miles   │ Stops    │
        ├──────────┼──────────┼─────────┼──────────┤
        │ Jul 12   │ Business │ 55,000  │ Nonstop  │
        │ Jul 15   │ Business │ 45,000  │ 1 stop   │
        │ Jul 19   │ Business │ 60,000  │ Nonstop  │
        └──────────┴──────────┴─────────┴──────────┘

You:    Show me the price trend as a graph.

Claude: YYZ -> LHR  |  Business  |  Price Trend

         80,000 ┤
         75,000 ┤          ╭╮
         70,000 ┤       ╭──╯│
         65,000 ┤      ╭╯   ╰╮
         60,000 ┼──╮  ╭╯     ╰╮
         55,000 ┤  ╰╮╭╯       │
         50,000 ┤   ╰╯        ╰╮
         45,000 ┤              ╰──
                Jul 01    Jul 15    Jul 29

        Min: 45,000 mi  Avg: 59,167 mi  8 dates

You:    Set up a watch — notify me if business drops under 50K.
Claude: [runs searchaero watch add YYZ LHR --max-miles 50000 --cabin business]
        Done. I'll check every 12 hours and notify you via ntfy.

You ask a question. The agent checks cached data, scrapes if needed, handles MFA, and presents the answer. One skill, end to end.

Example prompts:

  • "Scrape fresh data for cheapest business class from New York to London in July"
  • "Show me a price chart for YYZ to LAX for the next year"
  • "Find deals under 30K miles from any airport I've scraped"
  • "Set up a watchlist for paris to sanfran, business class, under 70K miles"

CLI reference

The agent uses these commands under the hood. You can also run them directly:

Action Command
Check cache searchaero query ORIG DEST --json
Show table searchaero query ORIG DEST
Show graph searchaero query ORIG DEST --graph
Show summary searchaero query ORIG DEST --summary
Find deals searchaero deals --json
DB status searchaero status --json
Scrape fresh searchaero search ORIG DEST --mfa-file --mfa-method email
Add alert searchaero alert add ORIG DEST --max-miles N
Check alerts searchaero alert check --json
Add watch searchaero watch add ORIG DEST --max-miles N
Check watches searchaero watch check --json
Diagnostics searchaero doctor

How scraping works

  1. Seataero opens a Chromium browser via Playwright and logs into united.com with your MP number
  2. United may send a verification code — the agent handles this automatically (email via Gmail) or asks you (SMS)
  3. Once logged in, searchaero scrapes the award calendar API (one request returns ~30 days of pricing)
  4. Results are stored in SQLite. Subsequent queries are instant (no scraping needed)
  5. The browser session stays warm between scrapes — MFA is typically only needed once per session

Rate limiting: Seataero adds delays between requests to avoid triggering United's bot detection. For recurring scrapes, use a minimum interval of 10 minutes between runs.

Troubleshooting

Problem Cause Fix
BROWSER CRASH detected United's Akamai bot detection blocked your IP Wait 10 minutes and retry, or use --proxy
MFA code times out The 5-minute code window expired Re-run the search — United will send a new code
No availability found No scraped data for this route yet Ask your agent to scrape it, or run searchaero search ORIGIN DEST
Database errors Corrupted SQLite file Delete ~/.searchaero/data.db and run searchaero setup
Repeated Akamai blocks Your home IP is flagged Wait 10–15 minutes, or use --proxy. See searchaero help proxy

Run searchaero doctor for a comprehensive diagnostic check.

More documentation

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

searchaero-0.2.0.tar.gz (68.7 kB view details)

Uploaded Source

Built Distribution

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

searchaero-0.2.0-py3-none-any.whl (71.2 kB view details)

Uploaded Python 3

File details

Details for the file searchaero-0.2.0.tar.gz.

File metadata

  • Download URL: searchaero-0.2.0.tar.gz
  • Upload date:
  • Size: 68.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for searchaero-0.2.0.tar.gz
Algorithm Hash digest
SHA256 03501d7a1d3b45b31690ee7eaf1cf7a8bc3af2499457ae82688a23242597a6e2
MD5 db7ffd979fa6253b1a5e5927e7ce9e15
BLAKE2b-256 db720c49f88982f8a24a41539937e85eb04f97737f0ac8885330a0534b49cb01

See more details on using hashes here.

File details

Details for the file searchaero-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: searchaero-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 71.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for searchaero-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f3b383b5e8254aa5669ba1c897877e3c5796ad92c865f947b168632de307bd68
MD5 23b9118228e496a57e7233e086cc9a22
BLAKE2b-256 0ef287c7d056d1c1efbb3810221d83879f864a279148d4d41edc3d006ea314bc

See more details on using hashes here.

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