Pre-auth anti-abuse gate
Many of the most valuable APIs on a public site can't sit behind a login — address lookups, product search, quote calculators, AI chat widgets. They're how the user gets to the login. But "no login required" isn't the same as "safe to leave wide open" — most of them cost real money on every call.
Why an open API is a security problem, not just an availability one
- Address lookup at checkout. Loqate, getAddress.io and Postcoder charge per autocomplete request — typically £0.001–£0.005. A scraper hammering
/api/address/lookup?postcode=…burns your vendor bill, not theirs, and the invoice arrives next month. - Pre-login pricing and quote pages. Comparison sites and aggregators (insurance, energy, FX, travel) call paid upstream providers before the user is identified. Every render is a paid lookup; a bot pulling 100k quote variants per hour can clear a five-figure vendor bill in a day.
- "Talk to our docs" widgets. An LLM-backed search or chat answer on a landing page issues an inference call per query — at roughly $0.01–$0.05 each, a few thousand bot requests is a real number. And LLMs are the new favourite scraping target.
- Maps, geocoding, place autocomplete. Google Places, Mapbox, Algolia all bill per query. Google Places autocomplete is ~$2.83 per 1,000 requests with no in-built caching.
- Your own cloud bill. Even endpoints that hit "free" internal data burn CPU, egress, and database read-units. Cloud Run will happily scale to absorb 100k req/s for you; your monthly invoice may not.
- Inventory and pricing leakage. Competitors scraping your pre-login product feed, stock levels, or live prices is the original use case for the gate — they pay nothing, you pay both the infra cost and the strategic cost of having your catalogue mirrored.
You can't put these endpoints behind a session — they precede the session. But you can put a gate between "any HTTP client on the planet" and "a browser that came from your own site and proved it with one round-trip." That gate is what this demo is.
How the gate works
This page calls a tiny Go backend that mints an HMAC-bound token and an HttpOnly cookie. The frontend then makes lookups carrying both. The cookie auto-attaches; the token must be explicitly sent as X-CSRF-Token. Every part has a deliberate rate limit.
Backend config (returned by /api/v1/mint)
Current token
(minting on load…)
Call the protected endpoint
Try to bypass
Open a terminal and try these.
curl -i http://localhost:5050/api/v1/lookup
curl -i -H "X-CSRF-Token: abc|9999999999|fakehash" http://localhost:5050/api/v1/lookup
BASE=http://localhost:5050
TOKEN=$(curl -s -c /tmp/jar "$BASE/api/v1/mint" | sed -nE 's/.*"token":"([^"]+)".*/\1/p')
curl -i -b /tmp/jar -H "X-CSRF-Token: $TOKEN" "$BASE/api/v1/lookup"
for i in $(seq 1 25); do
curl -s -o /dev/null -w "mint %{http_code}\n" http://localhost:5050/api/v1/mint
done
MAX_USES_PER_TOKEN requests, plus the per-IP token bucket forces them to slow down or rotate IPs (which itself costs money).
Demo vs production reality
The demo strips several production realities that meaningfully change the economics of scraping. In a real deployment the bot's job is much harder than what you see here:
| Demo (localhost) | Real deployment |
|---|---|
| Both requests round-trip in ~0.5ms | Each request adds 50–300ms (TLS handshake, network). Two requests per token-burst means the bot's wall-clock cost scales with (N_requests / MAX_USES_PER_TOKEN) × latency. |
Mint endpoint /api/v1/mint is unprotected (only the token bucket) |
Mint sits behind Cloudflare / Turnstile / Anubis / Akamai bot manager — the bot has to clear that challenge every time it needs a fresh token. |
| Tool's TLS fingerprint doesn't matter | requests.Session() has a JA3 fingerprint that doesn't match any real browser; gets flagged immediately by JA4-aware WAFs. |
| Per-IP token bucket only — and the IP is the docker bridge, so all local requests share it | Per-IP, per-ASN, per-subnet rate limits at every endpoint at the CDN and origin. Datacenter IP ranges (AWS, GCP, Hetzner) score worse than residential — and IP comes from X-Forwarded-For validated against the CDN's known range, not the inbound peer. |
| No SIEM / no anomaly detection | Every 403 / 429 logged; a single IP doing 100 token-mints in a minute pages someone. |
Need this built into your stack?
We help product and security teams design and ship pre-auth anti-abuse gates — HMAC-bound tokens, edge rate limits, Turnstile / Anubis bot scoring, and vendor-cost protection — across the public surfaces that can't sit behind a login.