Search for cheap flights by scraping Skiplagged. Supports one-way, round-trip, worldwide, and batch multi-leg queries. Automatically detects hidden-city tickets.
Hidden-city ticketing: Sometimes booking a flight to city C with a layover in city B is cheaper than flying directly to B. You book the full trip, get off at B, and skip the rest. This tool finds and flags those options.
Why "deadhead"? In aviation, a deadhead is a crew member riding a flight as a passenger without working. Same idea.
Inspired by and forked from go-skiplagged by @minormending.
The original repo is outdated and no longer works. Skiplagged added Cloudflare bot detection that blocks the plain HTTP requests it used. This fork fixes that by using a real Chrome session to clear the challenge before making requests.
Other changes:
- Batch mode for running multi-leg itineraries from a single JSON file, useful for agentic/automated workflows
- Hidden-city detection flagged in output
- One-way pricing fix: the original passed a return date even for one-way queries, causing the endpoint to return round-trip prices
- Improved CLI: flags work anywhere in the command
- Comprehensive test suite: 65 unit tests with full mock coverage across all packages
Requires Go 1.26+.
| Platform | Instructions |
|---|---|
| macOS | brew install go or download from go.dev/dl |
| Windows | Download the .msi installer from go.dev/dl and run it |
| Linux | Download from go.dev/dl or use your package manager (sudo apt install golang-go, sudo dnf install golang, etc.) |
Verify: go version
deadhead launches a real Chrome window to pass Skiplagged's Cloudflare bot detection. Chrome must be installed - it does not need to be your default browser.
macOS
brew install --cask google-chromeOr download from google.com/chrome. Chrome is found automatically via its standard app path.
Windows
Download and install from google.com/chrome. Chrome is found automatically via its standard install path.
Linux
# Debian / Ubuntu
sudo apt update && sudo apt install -y google-chrome-stable
# If google-chrome-stable is not in your repos, add the Google repo first:
wget -q https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo apt install ./google-chrome-stable_current_amd64.deb
# Fedora / RHEL
sudo dnf install google-chrome-stable
# Arch
yay -S google-chrome
# Chromium also works (lighter alternative)
sudo apt install chromium-browser # Debian/Ubuntu
sudo dnf install chromium # FedoraOption A - go install (recommended, no clone needed)
go install github.com/mattneto928/deadhead/cmd/deadhead@latestThis places deadhead (or deadhead.exe on Windows) in $HOME/go/bin. That directory must be in your PATH or the command won't be found after install.
If deadhead is not found after install, $HOME/go/bin is not in your PATH. Add it permanently:
macOS / Linux (zsh)
echo 'export PATH="$PATH:$HOME/go/bin"' >> ~/.zshrc
source ~/.zshrcmacOS / Linux (bash)
echo 'export PATH="$PATH:$HOME/go/bin"' >> ~/.bashrc
source ~/.bashrcRunning
export PATH=...directly in the terminal only applies to the current session. Writing it to~/.zshrcor~/.bashrcmakes it permanent.
Windows (PowerShell, permanent)
[Environment]::SetEnvironmentVariable("PATH", $env:PATH + ";$env:USERPROFILE\go\bin", "User")Restart PowerShell after running this.
Verify:
which deadhead # macOS / Linux
where deadhead # WindowsOption B - build from source
git clone https://github.com/MattNeto928/deadhead
cd deadhead
# macOS / Linux
make install # builds and copies to /usr/local/bin/deadhead
# macOS / Linux (without make)
go build -o deadhead ./cmd/deadhead/
sudo mv deadhead /usr/local/bin/
# Windows (PowerShell)
go build -o deadhead.exe .\cmd\deadhead\
# Then move deadhead.exe to a folder already in your PATH, e.g.:
Move-Item deadhead.exe "$env:USERPROFILE\go\bin\deadhead.exe"deadhead [OPTIONS] FROM [TO] DEPART [RETURN]
FROM origin airport or city code (e.g. NYC, JFK)
TO destination code, optional (omit for worldwide search)
DEPART departure date (yyyy-MM-dd)
RETURN return date, optional (omit for one-way)
Options:
-batch string JSON file with array of queries
-exclude string comma-separated airports to exclude
-leave-after int outbound departs after this hour (0-23)
-leave-before int outbound departs before this hour (0-23)
-return-after int return departs after this hour (0-23)
-return-before int return departs before this hour (0-23)
-max-price int max total price in USD
-travelers int number of travelers (default 1)
-out-json string save results to a JSON file
-out-md string save results to a Markdown file
-overwrite overwrite existing output file
-skip-worldwide skip the worldwide fare scan
-proxy string HTTP proxy URL
-help show help
deadhead NYC LAX 2026-05-12Launching browser...
Browser ready.
Searching NYC -> LAX on 2026-05-12...
Los Angeles, California (LAX) $126 one-way
EWR -> LAX $126 United Airlines 6:30 PM -> 9:33 PM [HIDDEN-CITY to LAS]
JFK -> LAX $144 JetBlue Airways 6:19 AM -> 9:28 AM
JFK -> LAX $144 JetBlue Airways 7:30 AM -> 10:41 AM
JFK -> LAX $144 Delta Air Lines 8:00 AM -> 11:05 AM
min outbound: $126
Search complete. 1 destination with available flights.
deadhead NYC LAX 2026-05-12 2026-05-19 --leave-before 13Launching browser...
Browser ready.
Searching NYC -> LAX (2026-05-12 -> 2026-05-19)...
Los Angeles, California (LAX) $144 round trip
JFK -> LAX $144 JetBlue Airways 6:19 AM -> 9:28 AM
JFK -> LAX $144 JetBlue Airways 7:30 AM -> 10:41 AM
JFK -> LAX $144 Delta Air Lines 8:00 AM -> 11:05 AM
min outbound: $144
LAX -> JFK $144 JetBlue Airways 7:05 AM -> 3:34 PM
LAX -> EWR $144 United Airlines 4:30 PM -> 12:59 AM
LAX -> EWR $144 United Airlines 9:00 PM -> 5:13 AM
min return: $144
Search complete. 1 destination with available flights.
deadhead NYC AUS 2026-05-12 2026-05-19 --max-price 200deadhead NYC 2026-05-12Launching browser...
Browser ready.
Searching worldwide from NYC on 2026-05-12...
Found 41 candidate destinations. Fetching flight details...
[1/41] BNA -- 21 flight(s) from $69
[2/41] PSP -- no qualifying flights
[3/41] SMF -- 1 flight(s) from $174
[4/41] CLT -- 38 flight(s) from $42
...
Nashville, Tennessee (BNA) $69 one-way
EWR -> BNA $69 Spirit Airlines 5:50 PM -> 7:22 PM
min outbound: $69
Charlotte, North Carolina (CLT) $42 one-way
EWR -> CLT $42 Spirit Airlines 8:30 PM -> 10:35 PM
min outbound: $42
...
Search complete. 40 destinations with available flights.
deadhead NYC 2026-05-12 --max-price 150 --leave-after 8 --leave-before 16deadhead NYC LAX 2026-05-12 2026-05-19 --travelers 2--exclude filters on the departure airport of each flight leg. For outbound flights this means the NYC-area airport you leave from; for return legs it filters on the arrival airport back home.
deadhead NYC LON 2026-05-12 --exclude EWR,LGAThis runs the search but drops any outbound flight that departs from EWR or LGA, leaving only JFK options.
deadhead NYC LON 2026-05-12 --out-json results.json --out-md results.mdNote: When
--out-jsonor--out-mdis provided, flight results are written to the file and suppressed on stdout. Progress and summary messages still appear on stderr as usual.
Create a file legs.json:
[
{ "from": "NYC", "to": "LGW", "depart": "2026-05-12" },
{ "from": "LGW", "to": "ZRH", "depart": "2026-05-16" },
{ "from": "ZRH", "to": "PRG", "depart": "2026-05-19" },
{ "from": "PRG", "to": "NYC", "depart": "2026-05-22" }
]deadhead --batch legs.json --out-json trip.jsonRunning 4 batch queries...
[1/4] NYC -> LGW (2026-05-12)
1 destination(s) with available flights.
London, England (LGW) $278 one-way
JFK -> LGW $278 Norse Atlantic UK 6:20 PM -> 6:20 AM
min outbound: $278
[2/4] LGW -> ZRH (2026-05-16)
1 destination(s) with available flights.
Zurich, Switzerland (ZRH) $136 one-way
LGW -> ZRH $136 easyJet 7:00 AM -> 9:50 AM
LGW -> ZRH $214 Swiss 9:25 AM -> 12:00 PM [HIDDEN-CITY to FRA]
min outbound: $136
...
Batch complete. 4 total result(s) across all queries.
Results saved to trip.json
All CLI options are available per-query in the batch JSON object:
| Field | Type | Description |
|---|---|---|
from |
string | Required. Origin code |
to |
string | Destination code (omit for worldwide) |
depart |
string | Required. Date as yyyy-MM-dd |
return |
string | Return date (omit for one-way) |
travelers |
int | Default 1 |
max_price |
int | Price ceiling |
leave_after |
int | Outbound departs after this hour |
leave_before |
int | Outbound departs before this hour |
return_after |
int | Return departs after this hour |
return_before |
int | Return departs before this hour |
exclude |
string | Comma-separated airports to exclude |
skip_worldwide |
bool | Skip worldwide scan for this query |
Hidden-City Detection
Multi-segment flights where the final airport does not match your destination are flagged as potential hidden-city tickets:
IST -> BKK $630 Turkish Airlines 1:55 AM -> 3:25 PM [HIDDEN-CITY to CNX]
PVG -> KIX $312 Japan Airlines 1:15 PM -> 4:35 PM [HIDDEN-CITY to HND]
Warning: Hidden-city ticketing violates most airline terms of service. Do not check bags. Any return segments on the same booking will be cancelled if you skip the final leg.
All packages have full unit test coverage. No browser or network access required - HTTP calls are mocked with httptest.
go test ./...Integration tests run against the real Skiplagged site and require Chrome and a network connection. They always use a departure date one month from today so they never query the past.
go test -v -tags integration ./integration/- On startup, Chrome opens a visible window to load
skiplagged.comand pass the Cloudflare challenge. Headless mode trips the bot detection, so it runs with a real window. Once the challenge clears, the session cookies are extracted and all subsequent requests are plain HTTP. - There is no public Skiplagged API. This tool hits their internal search endpoint (
skiplagged.com/api/search.php) that their own frontend uses. It returns JSON but is undocumented and subject to change. - Always omits the return date parameter. Passing one causes the endpoint to return round-trip pricing even for one-way queries.
See CONTRIBUTING.md.
MIT