Vercel's bandwidth pricing starts at $0.15–$0.40/GB depending on your plan. When AI crawlers like GPTBot, ClaudeBot, and meta-externalagent hit your site, they generate requests — and those requests consume bandwidth. The problem is that Vercel's dashboard only shows you total bandwidth. It doesn't break it down by requester, bot, or User-Agent.
Vercel Log Drains solve this. They pipe every request — including every bot hit — to an endpoint you control, in real time. This guide explains how they work and how to use them to build a per-bot cost breakdown.
A Vercel Log Drain is a webhook that Vercel calls with every log event from your deployments. This includes HTTP access logs — one event per request, with the full request metadata: method, URL, status, response size, and critically, the User-Agent header.
You configure a drain by giving Vercel an HTTPS endpoint URL. Vercel sends batched JSON payloads to that URL as your site receives traffic. You own the endpoint and decide what to do with the data.
Log Drains are configured per-team in your Vercel dashboard:
Vercel will start sending POST requests to your endpoint within seconds of the next deployment receiving traffic.
Each POST from Vercel contains a JSON array of log entries. Access log entries look like this:
[
{
"id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
"message": "GET /api/data 200 1234ms",
"timestamp": 1728054000000,
"source": "edge",
"projectId": "prj_abc123",
"deploymentId": "dpl_xyz789",
"host": "yourdomain.com",
"path": "/api/data",
"statusCode": 200,
"duration": 1234,
"responseBodySize": 8421,
"userAgent": "Mozilla/5.0 ...",
"method": "GET",
"scheme": "https",
"region": "iad1"
}
]
The field you care most about for AI crawler attribution is userAgent. It contains the raw User-Agent string of the requester. responseBodySize tells you how many bytes were transferred — this is what drives bandwidth costs.
Here are the User-Agent patterns for the major AI crawlers:
| Bot | Company | User-Agent contains |
|---|---|---|
| GPTBot | OpenAI | GPTBot |
| ChatGPT-User | OpenAI (browsing) | ChatGPT-User |
| ClaudeBot | Anthropic | ClaudeBot |
| anthropic-ai | Anthropic | anthropic-ai |
| meta-externalagent | Meta | meta-externalagent |
| Bytespider | ByteDance / TikTok | Bytespider |
| PerplexityBot | Perplexity | PerplexityBot |
| CCBot | Common Crawl | CCBot |
| Diffbot | Diffbot | Diffbot |
| YouBot | You.com | YouBot |
A simple classification function in Node.js:
const AI_BOTS = [
'GPTBot',
'ChatGPT-User',
'ClaudeBot',
'anthropic-ai',
'meta-externalagent',
'Bytespider',
'PerplexityBot',
'CCBot',
'Diffbot',
'YouBot',
];
function classifyUserAgent(ua) {
if (!ua) return null;
for (const bot of AI_BOTS) {
if (ua.includes(bot)) return bot;
}
return null;
}
Once you've classified the User-Agent, you can accumulate responseBodySize per bot and convert to cost:
// Vercel Pro bandwidth pricing: ~$0.40/GB
const COST_PER_GB = 0.40;
function bytesToCost(bytes) {
const gb = bytes / 1_000_000_000;
return gb * COST_PER_GB;
}
// Example: accumulate over a batch of log entries
function processBatch(entries, botBandwidth) {
for (const entry of entries) {
const bot = classifyUserAgent(entry.userAgent);
if (bot) {
botBandwidth[bot] = (botBandwidth[bot] || 0) + (entry.responseBodySize || 0);
}
}
}
// Output
function report(botBandwidth) {
for (const [bot, bytes] of Object.entries(botBandwidth)) {
const cost = bytesToCost(bytes);
console.log(`${bot}: ${(bytes / 1e6).toFixed(1)} MB — est. $${cost.toFixed(4)}`);
}
}
Your drain endpoint needs to be fast — Vercel will retry if it times out. Keep it simple: receive the payload, parse the entries, store the aggregated data, return 200 quickly.
// Express.js endpoint — runs on any Node server
app.post('/api/drain', express.json({ limit: '10mb' }), async (req, res) => {
// Respond immediately — don't await heavy processing
res.json({ ok: true });
const entries = Array.isArray(req.body) ? req.body : [];
for (const entry of entries) {
const bot = classifyUserAgent(entry.userAgent);
if (bot) {
await db.insert({
botName: bot,
url: entry.path,
sizeBytes: entry.responseBodySize || 0,
hitAt: new Date(entry.timestamp),
});
}
}
});
A few implementation notes:
{ ok: true } immediately and process asynchronously./api/drain?token=your-secret) or verify Vercel's HMAC signature if you're on Enterprise.Once you have per-bot bandwidth data, you have several options:
Add the high-cost bots to your robots.txt. Start with the ones consuming the most bandwidth. A Disallow: / directive for a specific User-Agent costs nothing and can immediately stop the bleeding.
User-agent: GPTBot
Disallow: /
User-agent: meta-externalagent
Disallow: /
User-agent: ClaudeBot
Disallow: /
Note: you need to block each User-Agent string separately. User-agent: * disallows paths for all bots but should only be used if you want to block everything including search engines.
Vercel's Firewall can rate-limit by User-Agent. This is more nuanced than a blanket robots.txt block — you can allow the bot to crawl, but cap it at a bandwidth-safe rate.
If a bot's daily bandwidth cost exceeds your threshold (e.g., $1/day = ~2.5 GB), you want to know. A simple daily scheduled job that queries your drain database and sends you a notification when any single bot exceeds the threshold gives you early warning before it becomes a billing crisis.
robots.txt won't be stopped by adding more rules to it. If your drain data shows a bot continuing to crawl after you've added a Disallow directive, you need firewall-level blocking — rate limits, IP blocks, or WAF rules targeting the specific User-Agent string.
Here's the full architecture for a minimal AI crawler cost monitor using Vercel Log Drains:
The actual volume of data is small. Even at 100,000 requests/day, if you only store AI crawler hits (typically 1–5% of total traffic), you're looking at a few thousand rows per day — easily handled by any database.
Vercel's built-in analytics show you traffic sources like "Direct", "Search", and "Social". They do not surface bot traffic separately, and they certainly don't break it down by crawler company. The only way to get bot-level attribution is through Log Drains or a third-party log analysis tool.
This means most developers on Vercel are flying blind on AI crawler costs. They see the bandwidth total and assume it's user traffic. When the bill spikes, they look at their feature changes, their deployment frequency, their user acquisition. The actual culprit — a newly aggressive AI crawler — is invisible.
Log Drains are the only Vercel-native mechanism to close this gap.
Building and maintaining a drain endpoint, parsing User-Agents, storing aggregates, and setting up alerts takes a few days of engineering time. CrawlGuard does all of it: connect your Vercel project, get a per-bot cost dashboard and alerts immediately.
First, check whether your site is blocking AI crawlers today (takes 10 seconds):
Check your site free → Get early access