Stack Spy API

Detect the full technology stack of any website. JSON over HTTPS, instant cache-first responses, no setup required for the free tier.

Get the Postman collection

One-click import. Pre-configured environment variables (baseUrl, domain, apiKey) and an auto-store login script.

Download collection

Getting started

All endpoints are served over HTTPS at https://api.stack-spy.com. The free tier requires no authentication — just call GET /scan?domain=... and you are done.

curl# Fast scan — returns cached result if available curl "https://api.stack-spy.com/scan?domain=stripe.com" # Full scan with BuiltWith merge (slower, richer) curl "https://api.stack-spy.com/scan?domain=stripe.com&mode=full"

Authentication

The free tier is anonymous — no key required. Authenticated calls (Bearer JWT) unlock BuiltWith-powered insights and watchlist features. Get a token by calling POST /auth/login.

Tip: never embed your JWT in client-side code. Treat it like a password and rotate it periodically.
headerAuthorization: Bearer <your-jwt-here>

Scan endpoints

The core of Stack Spy. Returns the technology stack of any public domain. Cache-first: if the domain has been scanned within the last 30 days, you get an instant response (~50 ms).

GET /scan

Scan a domain. Cache-first, then triggers a fresh scan in the background if needed.

domainstringrequiredHostname to scan, e.g. stripe.com. Protocol prefix and path are stripped automatically.
modestringultrafast | fast (default) | full. Controls scan depth and BuiltWith inclusion.
timeoutintHTTP timeout for the scanner, in seconds (3-30). Default: 10.
forceboolIf true, bypasses the 30-day cache. Use sparingly.

Cache lookup

Inspect a cached scan without triggering a new one. Returns 404 if the domain has never been scanned.

GET /cache/{domain}

Returns the latest cached technologies for {domain}, or 404.

Statistics

Aggregate statistics over the public Stack Spy index. Useful for trend reports and comparison dashboards.

GET /stats/tech-frequency

Returns the frequency of each technology category across all indexed domains.

Auth endpoints

Create an account, log in, and inspect the current user. Login returns a JWT to use as Bearer token.

POST /auth/register

Create an account with email + password. Returns a JWT.

POST /auth/login

Returns a JWT. Use it as Authorization: Bearer … on subsequent calls.

GET /auth/me

Returns the authenticated user profile. Requires Bearer token.

Watchlist authenticated

Track domains and get notified when their stack changes. Requires a JWT.

POST /watchlist

Add a domain to your watchlist. Body: { "domain": "stripe.com" }.

GET /watchlist

List all domains you are currently watching.

GET /watchlist/{domain}

Watch status & latest change diff for a single domain.

Response format

All responses are JSON, UTF-8 encoded. Successful scans look like this:

json{ "domain": "stripe.com", "technologies": { "CDN": ["Cloudflare"], "Analytics": ["Google Analytics", "Hotjar"], "Payments": ["Stripe"], "JavaScript": ["React", "Ruby on Rails"] }, "meta": { "total_technologies": 7, "categories": 4, "scan_time_s": 3.21, "http_status": 200, "mode": "fast" }, "cache": { "hit": true, "scanned_at": "2026-04-26T10:00:00Z", "ttl_days": 30 } }

Errors & rate limits

Standard HTTP status codes. Errors include a JSON body with a detail field describing the problem.

StatusMeaning
200OK — scan or lookup succeeded.
400Bad request — missing or invalid parameter (usually domain).
401Unauthorized — Bearer token missing, invalid, or expired.
404Not found — usually a cache lookup with no matching scan.
429Rate limited — slow down. The free tier allows 30 calls/minute per IP.
502Upstream scanner error — retry in a few seconds with exponential backoff.
Rate limits: /scan is capped at 30 requests/minute and 200 requests/hour per IP on the free tier. Authenticated accounts get higher limits — contact us for enterprise quotas.

Ready to integrate?

Download Postman collection