Discover, diff, and hunt ghost API endpoints for bug bounty hunting
API Ghost Hunter is a Python-based bug bounty tool that helps security researchers discover ghost API endpoints — old API endpoints that developers forgot to delete or forgot to protect with authorization when updating their API.
When developers update their API:
- They add new endpoints to the documentation
- They remove old endpoints from the documentation
- But they sometimes forget to delete the old endpoint code on the server
- Or they forget to add authorization to endpoints that need it
These forgotten endpoints are ghost endpoints — they still work but are no longer documented, making them prime targets for security vulnerabilities.
┌─────────────┐ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐
│ Scan Target │────▶│ Save Snapshot│────▶│ Compare │────▶│ Probe Ghosts │
│ (OpenAPI) │ │ (JSON file) │ │ Snapshots │ │ (HTTP probe) │
└─────────────┘ └──────────────┘ └─────────────┘ └──────────────┘
│ │
▼ ▼
Added / Removed Alive? Auth Bypass?
Modified / Unchanged
- Scan a target's API documentation (OpenAPI/Swagger spec) and save a snapshot
- Archive — query the Wayback Machine for historical API specs and create snapshots from archived versions
- Compare snapshots from different points in time (current vs. previous, or current vs. archived)
- Identify endpoints that were removed from the docs
- Probe those removed endpoints to see if they're still alive (ghosts!)
- Detect authorization bypass on ghost endpoints
- Auto-discovery of OpenAPI/Swagger specs (tries 60+ common paths)
- Wayback Machine integration — fetch archived API specs from the Internet Archive to find old endpoints
- Snapshot management — save and compare API endpoint states over time
- Deep diffing — detects added, removed, modified, and unchanged endpoints
- Ghost endpoint hunting — probes removed endpoints to check if they still respond
- Authorization bypass detection — checks if auth-required endpoints respond without auth
- Dual-probe authentication — probe with and without auth headers to compare responses
- Response snippet capture — records first 500 characters of ghost endpoint responses
- JavaScript scanning — extracts API endpoints from JS files (fetch, axios, XMLHttpRequest)
- Proxy support — route all requests through HTTP/HTTPS proxies
- Custom headers — send custom headers via JSON string or file
- Rate limiting — configurable delay between requests to avoid overwhelming targets
- Multiple report formats — console (rich tables), JSON, HTML, and Markdown
- Dark-themed HTML reports with color-coded HTTP methods and response snippets
git clone https://github.com/yourusername/api-ghost-hunter.git
cd api-ghost-hunter
pip install -r requirements.txt
pip install -e .git clone https://github.com/yourusername/api-ghost-hunter.git
cd api-ghost-hunter
pip install -r requirements.txt
python -m api_ghost_hunter --helpThe tool installs two console commands:
api-ghost-hunter— full nameagh— short alias
# Auto-discover the API spec
api-ghost-hunter scan https://example.com
# Or specify the spec URL directly
api-ghost-hunter scan https://example.com --spec-url https://example.com/api/swagger.json
# Also scan JavaScript files for additional endpoints
api-ghost-hunter scan https://example.com --scan-js
# Use a proxy and custom headers
api-ghost-hunter scan https://example.com --proxy http://127.0.0.1:8080 --headers '{"X-Custom":"value"}'# Find and save archived API specs from the Wayback Machine
api-ghost-hunter archive https://example.com
# Specify a known spec URL to search for in archives
api-ghost-hunter archive https://example.com --spec-url https://example.com/openapi.json
# Filter by date range
api-ghost-hunter archive https://example.com --from-date 20230101 --to-date 20251231# Scan again later to create a second snapshot
api-ghost-hunter scan https://example.com# Full hunt: scan + compare with previous + probe removed endpoints + check archives
api-ghost-hunter hunt https://example.com --probe --check-archives
# Just compare two specific snapshots
api-ghost-hunter diff snapshots/example.com_2026-01-01T10-00-00.json snapshots/example.com_2026-01-15T10-00-00.json --probe
# Find ghosts from existing snapshots
api-ghost-hunter ghosts https://example.com# Generate all report formats
api-ghost-hunter hunt https://example.com --probe --report-format all
# Generate HTML report only
api-ghost-hunter diff old.json new.json --format html -o report.html
# Generate JSON report
api-ghost-hunter ghosts https://example.com --report-format json -o ghosts.jsonapi-ghost-hunter scan TARGET [OPTIONS]| Option | Description |
|---|---|
-s, --spec-url URL |
Direct URL to OpenAPI/Swagger spec |
--scan-js |
Also scan JavaScript files for endpoints |
-o, --output-dir DIR |
Directory to save snapshots (default: snapshots) |
--headers HEADERS |
Custom headers as JSON string or file path |
Example:
api-ghost-hunter scan https://api.example.com --spec-url https://api.example.com/v3/openapi.json --scan-jsapi-ghost-hunter list [OPTIONS]| Option | Description |
|---|---|
-d, --snapshot-dir DIR |
Snapshot directory (default: snapshots) |
-t, --target URL |
Filter by target URL |
Example:
api-ghost-hunter list --target example.comapi-ghost-hunter diff OLD_SNAPSHOT NEW_SNAPSHOT [OPTIONS]| Option | Description |
|---|---|
-f, --format FORMAT |
Output format: console, json, html, markdown, all |
-o, --output FILE |
Output file path |
--probe |
Probe removed endpoints to find ghosts |
--auth-header HEADER |
Auth header for probing (e.g. Authorization: Bearer token) |
--delay SECONDS |
Delay between probes (default: 0.5) |
Example:
api-ghost-hunter diff snapshots/old.json snapshots/new.json --format html -o report.html --probeapi-ghost-hunter hunt TARGET [OPTIONS]| Option | Description |
|---|---|
-s, --spec-url URL |
Direct URL to OpenAPI/Swagger spec |
--scan-js |
Also scan JavaScript files |
--probe |
Probe removed endpoints to find ghosts |
--check-archives |
Also check Wayback Machine for old API specs |
--auth-header HEADER |
Auth header for probing (e.g. Authorization: Bearer token) |
--headers HEADERS |
Custom headers as JSON string or file path |
-f, --report-format FORMAT |
Report format: console, json, html, markdown, all |
-o, --output FILE |
Output file path |
-d, --snapshot-dir DIR |
Snapshot directory |
--delay SECONDS |
Delay between probes (default: 0.5) |
Example:
api-ghost-hunter hunt https://example.com --probe --check-archives --scan-js --report-format all -o hunt_reportapi-ghost-hunter ghosts TARGET [OPTIONS]| Option | Description |
|---|---|
-f, --report-format FORMAT |
Report format: console, json, html, markdown, all |
-o, --output FILE |
Output file path |
-d, --snapshot-dir DIR |
Snapshot directory |
--auth-header HEADER |
Auth header for probing (e.g. Authorization: Bearer token) |
--delay SECONDS |
Delay between probes (default: 0.5) |
Example:
api-ghost-hunter ghosts https://example.com --report-format json -o ghost_report.jsonapi-ghost-hunter archive TARGET [OPTIONS]| Option | Description |
|---|---|
-s, --spec-url URL |
Direct URL to spec (uses this URL for archive search) |
-o, --output-dir DIR |
Directory to save snapshots (default: snapshots) |
--from-date YYYYMMDD |
Start date for Wayback Machine search |
--to-date YYYYMMDD |
End date for Wayback Machine search |
--limit N |
Max archived versions to fetch per URL (default: 50) |
Example:
api-ghost-hunter archive https://example.com --from-date 20230101 --to-date 20251231 --limit 100These options can be passed before any command:
| Option | Description |
|---|---|
-v, --verbose |
Enable verbose (debug) output |
-t, --timeout SECONDS |
Request timeout (default: 15) |
--no-verify-ssl |
Disable SSL certificate verification |
--proxy URL |
HTTP/HTTPS proxy URL (e.g. http://127.0.0.1:8080) |
-h, --help |
Show help |
--version |
Show version |
The archive command and --check-archives flag use the Wayback Machine CDX API to find historical snapshots of API specification files.
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Query CDX API │────▶│ Fetch Archived │────▶│ Parse & Save │
│ for spec URLs │ │ Spec Content │ │ Snapshots │
└──────────────────┘ └──────────────────┘ └──────────────────┘
- The archiver queries the CDX API for all common spec paths (
/openapi.json,/swagger.json, etc.) - For each archived version found, it fetches the actual content from
web.archive.org - The content is parsed as JSON or YAML OpenAPI/Swagger spec
- Valid specs are converted to snapshots with an
archive_timestamp - These snapshots can be diffed against the current API to find removed endpoints
# Step 1: Find archived specs from the past
api-ghost-hunter archive https://target.com --from-date 20220101 --to-date 20231231
# Step 2: Scan the current API
api-ghost-hunter scan https://target.com
# Step 3: Diff the oldest archive snapshot with the current one
api-ghost-hunter list --target target.com
api-ghost-hunter diff snapshots/old_archive.json snapshots/current.json --probe# Scan + check archives + diff + probe in one command
api-ghost-hunter hunt https://target.com --probe --check-archives --report-format all -o full_report- Baseline scan — Scan the target's API when you start the bounty
- Archive search — Use the Wayback Machine to find old API specs from months or years ago
- Monitor for changes — Re-scan periodically (weekly/monthly)
- Hunt ghosts — When endpoints disappear from the docs, probe them:
- Still alive? -> Potential IDOR or information disclosure
- Auth bypass? -> Potential broken access control
- Deprecated but alive? -> Potential unpatched vulnerabilities
- Track API changes over time
- Identify deprecated endpoints that should be removed
- Find authorization gaps in the API
- Compare API versions (v1 vs. v2) for leftover endpoints
- Catch leftover endpoints from old API versions
- Verify authorization is properly applied
- Track API evolution with snapshot history
Rich, color-coded tables in your terminal with:
- Summary of changes (added/removed/modified/unchanged)
- Full endpoint details with auth status
- Ghost probing results with auth bypass detection
- Response snippets from alive ghost endpoints
- Archive timestamp display for Wayback Machine snapshots
Machine-readable JSON with full endpoint details, diff results, and ghost probing data including response snippets and auth probe results.
Dark-themed, standalone HTML file with:
- Summary cards (added/removed/modified/unchanged)
- Color-coded HTTP methods (GET=green, POST=orange, DELETE=red, etc.)
- Ghost endpoint highlighting (red for removed, green for alive)
- Response snippet column for ghost endpoints
- Archive timestamp info for Wayback Machine snapshots
GitHub-flavored Markdown for easy inclusion in issues, PRs, or documentation. Includes response snippets for alive ghost endpoints.
Time T1: API has endpoints A, B, C, D (all documented)
│
│ Developer updates API
│ Removes B and C from docs
│ But forgets to delete B and C on the server
▼
Time T2: API has endpoints A, D, E (documented)
Endpoints B, C still work but are NOT documented = GHOSTS!
API Ghost Hunter:
1. Scans T1 snapshot -> [A, B, C, D]
2. Scans T2 snapshot -> [A, D, E]
3. Diffs them -> Removed: [B, C] Added: [E]
4. Probes B and C -> Still alive? Auth bypass?
5. Reports ghosts!
Time T0 (archived): API had endpoints A, B, C, D, E, F (archived on Wayback Machine)
│
│ Developer removed B, C, E, F from docs over time
│ But forgot to delete server code
▼
Time T1 (current): API has endpoints A, D (documented)
Endpoints B, C, E, F still work = GHOSTS!
API Ghost Hunter:
1. Archives T0 from Wayback Machine -> [A, B, C, D, E, F]
2. Scans T1 current -> [A, D]
3. Diffs them -> Removed: [B, C, E, F]
4. Probes B, C, E, F -> Still alive? Auth bypass?
5. Reports ghosts!
api-ghost-hunter/
├── README.md # This file
├── LICENSE # MIT License
├── requirements.txt # Python dependencies
├── setup.py # Package setup
├── .gitignore # Git ignore rules
├── api_ghost_hunter/ # Main package
│ ├── __init__.py # Package init
│ ├── __main__.py # Entry point (python -m api_ghost_hunter)
│ ├── cli.py # Click-based CLI commands
│ ├── models.py # Data models (Endpoint, Snapshot, DiffResult, GhostEndpoint)
│ ├── fetcher.py # HTTP fetcher & spec discovery (60+ paths)
│ ├── parser.py # OpenAPI/Swagger & JS endpoint parser
│ ├── snapshot.py # Snapshot save/load/list management
│ ├── differ.py # Snapshot comparison engine
│ ├── analyzer.py # Ghost endpoint prober & auth bypass detector
│ ├── archiver.py # Wayback Machine CDX API integration
│ ├── reporter.py # Console/JSON/HTML/Markdown report generator
│ └── utils.py # Utility functions (headers, timestamps, URLs)
├── tests/ # Test suite
│ ├── __init__.py
│ ├── test_models.py # Data model tests
│ ├── test_differ.py # Diff engine tests
│ ├── test_parser.py # OpenAPI & JS parser tests
│ └── test_archiver.py # Wayback Machine archiver tests (mocked)
└── examples/ # Example files
└── sample_openapi.json # Sample OpenAPI spec for testing
# Day 1: First scan
api-ghost-hunter scan https://target.com
# Day 30: Second scan
api-ghost-hunter scan https://target.com
# Day 30: Compare and hunt ghosts
api-ghost-hunter ghosts https://target.com --report-format all -o day30_report# Search for archived API specs from 2023
api-ghost-hunter archive https://target.com --from-date 20230101 --to-date 20231231
# Scan current API
api-ghost-hunter scan https://target.com
# List all snapshots (current + archived)
api-ghost-hunter list --target target.com
# Diff oldest archive with current and probe ghosts
api-ghost-hunter diff snapshots/target_com_archive.json snapshots/target_com_current.json --probe --auth-header "Authorization: Bearer <token>"# Scan old API version
api-ghost-hunter scan https://api.target.com --spec-url https://api.target.com/v1/swagger.json -o snapshots/v1
# Scan new API version
api-ghost-hunter scan https://api.target.com --spec-url https://api.target.com/v2/openapi.json -o snapshots/v2
# Compare
api-ghost-hunter diff snapshots/v1/old.json snapshots/v2/new.json --format html -o api_diff.htmlapi-ghost-hunter hunt https://target.com \
--scan-js \
--probe \
--check-archives \
--report-format all \
-o full_hunt_report \
--no-verify-ssl \
--timeout 30 \
--proxy http://127.0.0.1:8080# Create a headers file
echo '{"X-API-Key": "your-key", "X-Custom-Header": "value"}' > headers.json
# Scan with custom headers
api-ghost-hunter scan https://target.com --headers headers.json# Install test dependencies
pip install pytest
# Run all tests
pytest tests/ -v
# Run specific test file
pytest tests/test_models.py -v
# Run with coverage (optional)
pip install pytest-cov
pytest tests/ --cov=api_ghost_hunter --cov-report=term-missingThis tool is designed for authorized security testing and bug bounty hunting only. Always ensure you have proper authorization before scanning any target. The authors are not responsible for any misuse of this tool.
This project is licensed under the MIT License — see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Made for the bug bounty community