How to Track Real 404 Errors Using Cloudflare’s GraphQL API (Free Tier)
03 Sep 26 (Today)
Finding genuine 404 errors in your server logs can feel like finding a needle in a haystack of automated bot traffic and vulnerability scanners. I recently put together a query to check visits and track down missing pages directly from a Cloudflare host.
Surprisingly, this is entirely possible—and highly capable—even on Cloudflare's Free tier. You don't need an Enterprise plan to start running granular queries on your traffic.
The Anti-Bot 404 Query
When you look at your 404 logs, a massive percentage of them are bots blindly guessing URLs looking for .env files, WordPress admin panels, or SQL dumps.
The GraphQL query below filters out that noise so you can see the actual missing pages your real users are hitting. Just swap "INSERT HERE" with your appropriate zoneTag (found on your Cloudflare dashboard's overview page).
query {
viewer {
zones(filter: { zoneTag: "INSERT HERE" }) {
httpRequestsAdaptiveGroups(
filter: {
datetime_geq: "2026-08-26T00:00:00Z"
datetime_leq: "2026-08-27T00:00:00Z"
edgeResponseStatus: 404
AND: [
{ clientRequestPath_notlike: "%.txt%" }
{ clientRequestPath_notlike: "%.jpg%" }
{ clientRequestPath_notlike: "%.jpeg%" }
{ clientRequestPath_notlike: "%.png%" }
{ clientRequestPath_notlike: "%.webp%" }
{ clientRequestPath_notlike: "%.css%" }
{ clientRequestPath_notlike: "%.php%" }
{ clientRequestPath_notlike: "%.git%" }
{ clientRequestPath_notlike: "%.env%" }
{ clientRequestPath_notlike: "%.json%" }
{ clientRequestPath_notlike: "%.github%" }
{ clientRequestPath_notlike: "%/_ignition%" }
{ clientRequestPath_notlike: "%wp-%" }
{ clientRequestPath_notlike: "%admin" }
{ clientRequestPath_notlike: "%wordpress%" }
{ clientRequestPath_notlike: "%.aws%" }
{ clientRequestPath_notlike: "%.well-known%" }
{ clientRequestPath_notlike: "%/cdn-cgi/%" }
{ clientRequestPath_notlike: "%/cgi-bin/%" }
{ clientRequestPath_notlike: "%.xml%" }
{ clientRequestPath_notlike: "%secrets.json%" }
{ clientRequestPath_notlike: "%/wp/" }
{ clientRequestPath_notlike: "%.js" }
{ clientRequestPath_notlike: "%.sql" }
]
}
limit: 200
orderBy: [count_DESC]
) {
count
dimensions {
clientRequestPath
edgeResponseStatus
}
}
}
}
}
How to Execute the Query
To run this, you will need to hit Cloudflare's GraphQL endpoint: https://graphql.cloudflare.com/explorer.
Important limit for Free Tier: While the API is fully accessible, Free tier accounts typically have strict data retention limits for analytics. Ensure your
datetime_geqanddatetime_leqfall within this recent window, otherwise the API will return an error.
Tweaking the Query: Finding Missing Images
Aside from scanning for missing web pages, you can easily invert the logic of this query to find missing image URLs. This is incredibly helpful for QAing a site after a migration to ensure no .png or .jpg assets were left behind.
To do this, remove the long list of exclusions and replace the AND block with an OR block that specifically targets image extensions using the like operator:
OR: [
{ clientRequestPath_like: "%.jpg%" }
{ clientRequestPath_like: "%.jpeg%" }
{ clientRequestPath_like: "%.png%" }
{ clientRequestPath_like: "%.webp%" }
]
By tweaking the clientRequestPath, Cloudflare’s GraphQL API becomes a highly flexible, free monitoring tool that catches broken links before your users have to report them.