Crawler logs

Platform log drains

Paste an endpoint and a token into your hosting platform log-drain settings. No code to deploy.

If your host can forward request logs to an HTTP endpoint — Vercel, Netlify, Fly and most others — this is the whole setup. No code, and the logs are edge logs, so they include requests your CDN answered without touching your origin.

Prerequisites

  • Permissions: admin or owner.
  • A host with an HTTP log drain feature. These are often on a paid tier; check your platform's current pricing.

1. Get your endpoint and token

  1. Open the brand's Settings → Crawler logs.
  2. Select Create token.
  3. Copy the endpoint and the token.

The token is shown once. It cannot be retrieved later, only replaced — and creating a new one immediately revokes the old one, which will stop a drain that is already working.

2. Add the drain on your platform

Point your platform's log drain at the endpoint with the token as a header.

SettingValue
URLthe endpoint from step 1
HeaderX-Shruwd-Ingest-Token: YOUR_TOKEN
Content typeapplication/x-ndjson
FormatNDJSON, one JSON object per line, or one JSON array of objects

On Vercel

Drains need a Pro or Enterprise team. On Hobby with Cloudflare in front of the site, use the forwarder Worker instead. Hobby without Cloudflare in front has no log path yet.

  1. Open Team Settings → Drains → Add Drain and choose Logs.
  2. Name the drain and select the project.
  3. Select the sources static, lambda, edge, external, redirect and firewall. firewall is the one that records the requests Vercel's firewall refused.
  4. Select the production environment. Add no sampling rule, so every request is sent.
  5. Choose Custom Endpoint: the endpoint from step 1, format NDJSON or JSON, and the custom header X-Shruwd-Ingest-Token: YOUR_TOKEN.
  6. Select Create Drain. Vercel tests the endpoint, which answers 200.

Keep Team Settings → Security & Privacy → IP Address Visibility on. With IP addresses hidden, Vercel sends no client IP, and no hit can be verified.

3. Check the fields

Shruwd reads these fields per line. Common alternative spellings — ClientIP, clientip, remote_addr — are understood, so most platforms work as they come. Vercel's format works as it is, including the request details it nests under proxy.

FieldRequiredUsed for
client_ipYesVerifying the hit is really from the crawler it claims to be
user_agentYesIdentifying which bot. Lines without one are dropped
timestampNoDefaults to arrival time. ISO 8601
hostNoTelling your domains apart
pathNoPer-page diagnostics
statusNoDetecting crawlers being refused
method, bytesNoFiltering and volume

If your host offers drain sampling, keep it at 100%. Crawler numbers are presented as exact counts, and a sampled drain would make them partial.

A single line looks like this:

json
{"timestamp":"2026-09-09T10:00:00Z","host":"example.com","path":"/pricing","user_agent":"Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)","status":200,"client_ip":"23.98.142.176","method":"GET","bytes":18234}

4. Test before relying on it

Add ?validate=1 to the endpoint to parse a sample and report on it without writing anything.

curl -X POST "YOUR_ENDPOINT?validate=1" \
  -H "X-Shruwd-Ingest-Token: YOUR_TOKEN" \
  -H "Content-Type: application/x-ndjson" \
  -d '{"timestamp":"2026-01-01T00:00:00Z","host":"example.com","path":"/","user_agent":"GPTBot","status":200,"client_ip":"1.2.3.4"}'

usable: true means the endpoint and token are both good. Anything else names what is missing.

5. Confirm it is live

Within a few minutes of real traffic, Settings → Crawler logs moves from awaiting first logs to active, and Last received fills in.

Response codes

CodeMeaning
202Accepted (200 to Vercel, which asks for it). Parsing happens afterwards, so this does not mean the lines were usable — use ?validate=1 to check that
401Wrong or revoked token
413Batch over the size cap
422Only with ?validate=1: the sample can't be used, and reason says why

Next steps