SELF-SERVE · LOG ANALYSIS
What your own server logs already know
The free scan on the homepage probes your site from the outside. This page runs a different tool against a different source: your own access logs. Free, open source, and it never leaves your machine.
What this answers that a scan can't
The homepage scan fetches your page once with a browser user-agent and once each with twelve AI-crawler user-agents, and reports what it gets back. That tells you what content exists in your raw HTML, what your robots.txt permits, and how fast your server answers — all of it true regardless of who's asking, so none of it needs further confirmation.
What it cannot tell you is who actually showed up. Our scan runs from one datacenter address, declaring a crawler's name in a request header — it is an outside requester claiming to be GPTBot, not GPTBot itself. Vendors verify their real crawlers by published IP range, so a security layer can treat our probe differently from the genuine bot in either direction, and we'd have no way to tell from outside.
Your server logs settle it, because they recorded the real requests: which AI crawlers genuinely reached your site, which pages they took, and which ones gave up waiting before your server finished answering. That last one — a fetch abandoned mid-request — never generates an error page and never fires your analytics. It only exists in the log line.
Runs on your machine. Nothing is uploaded.
This is not a service you send your logs to. You download an open-source script, run it against files that never leave your own computer or server, and read the report it writes next to them. We never see your logs, your traffic, or your domain. There is no upload step to skip — the tool has no network calls in its normal path, and the one optional exception (fetching a vendor's published IP ranges for --verify) talks to OpenAI, Perplexity, Microsoft or Google, never to us.
Get it running
The engine is drain_parser.py inside the open-source geo-crawl-audit repo. Clone it — it's plain Python 3 standard library, nothing to pip install:
git clone https://github.com/abouchard11/geo-crawl-audit.git cd geo-crawl-audit
It reads two kinds of log source. Use whichever one matches what you already have.
Vercel Log Drain export (NDJSON or JSON)
Vercel's runtime logs alone aren't enough — they only cover function invocations and miss most bot traffic, which hits static and edge-cached pages. Set up a Log Drain instead: Team Settings → Drains → new drain, sources static, edge and lambda, format NDJSON, delivered to storage you control. Then point the script at the exported files:
python3 scripts/drain_parser.py logs/*.ndjson --out ./audit-results --verify
nginx / Apache combined access logs
If you already have standard combined-format access logs, no export step is needed — point the script straight at them:
python3 scripts/drain_parser.py access.log --format combined --verify --out ./audit-results
--verify checks every hit's IP address against the crawler vendor's published IP ranges (OpenAI, Perplexity, Microsoft, Google — fetched live over HTTPS, the only network call the script makes) and splits the traffic into verified, authenticated crawlers versus impostors — anyone can send a User-Agent: GPTBot header, and plenty of scrapers do. Without --verify you get hit counts by claimed identity only; with it, you get the honest split.
What the output tells you
Both commands write audit-results/bot_log_report.md (a readable table, also printed to your terminal) and bot_log_stats.json (the same data, machine-readable). Per bot, it reports:
- Total hits, and a status-code breakdown across 2xx / 3xx / 4xx / 5xx
- 499s, called out on their own. That code means the crawler closed the connection before your server sent a reply — it gave up waiting. There's no error page, no alert, and nothing in your analytics; the log line is the only record it ever happened. A high 499 count on a bot points straight at slow time-to-first-byte on the paths it was trying to fetch.
- Its top crawled paths, so you know what it actually read, not just that it visited
- First-seen and last-seen timestamps, so you can spot a bot that used to show up and stopped
- With --verify: verified hits vs. unverified (impostor) hits, by IP
The script also flags problems directly: any bot with an error rate over 5%, and any bot with a nonzero 499 count, both called out in a dedicated section of the report so you don't have to spot them in a table yourself.
"No AI bot traffic at all" is itself a finding
An empty report doesn't mean the tool failed — it means one of two things, and it's worth working out which. Either your logs don't cover the requests that matter (Vercel runtime logs alone miss static and edge traffic, which is most of where bots land — check that you're reading a full Log Drain export, not just the function-invocation log), or your logs are complete and nothing is finding your site yet. The second one is a real, useful answer: it means the visibility problem is upstream of anything a technical fix addresses, and it's better to know that now than to assume you're being crawled and be wrong.
Where people get stuck
The script hands you accurate numbers. It doesn't tell you which of those numbers is worth acting on, and that's usually where a self-serve run stalls out: a table of hit counts and status codes with no ranking of what actually costs you something commercially.
That's what the Verified AI Search Audit adds on top of what this page gives you free: interpretation of the numbers, a Search Console join that shows which of the affected pages actually carry search demand, repeated answer-engine sampling instead of a single run, and paste-ready fixes for your developer. No pushy pitch here — the free scan and this log tool already tell you a great deal on their own; the audit is for when you want the rest connected for you.
Would rather not run it yourself?
Everything above is a script you run by hand, on demand. If you'd rather have your logs analyzed continuously and streamed to you automatically instead of run manually each time, see the hosted version.