Home › Cloudflare API analytics without an SDK
API analytics on Cloudflare, without an SDK
Most API analytics tools ask you to install a library in every service and language you run. A reverse proxy is the alternative: requests pass through a small edge function that forwards them to your origin and records one event per request. No code in your API is required to start.
How it works
- Your client calls the proxy URL instead of your origin.
- A Cloudflare Worker forwards the request (method, path, query, headers, body) to your origin and streams the response back.
- After the response is on its way, the Worker records method, normalized endpoint, status, latency, sizes, customer and plan. Bodies aren't stored.
That's how API Meter is built. You can also build it yourself; the steps below show both.
Option A: use API Meter (about five minutes)
- Sign up with your email, API name and https origin.
- Serve the ownership file at
/.well-known/api-meter-<token>.txton your origin and click Verify. - Swap the base URL in your client or SDK config:
# before https://api.acme.dev/v1/orders/123 # after https://api-meter-proxy.marc-cf2.workers.dev/p/your-slug/v1/orders/123
Optional: return X-MSA-Customer-Id and X-MSA-Plan response headers from your origin to attribute each request to a customer. Without them, API Meter uses a salted hash of the API key. Details in the header reference.
Option B: build your own Worker
A minimal proxy Worker looks like this. It forwards traffic and writes one data point per request to Workers Analytics Engine (enable it in your Cloudflare dashboard and add an analytics_engine_datasets binding first):
export default {
async fetch(req, env, ctx) {
const url = new URL(req.url);
const upstream = new URL(url.pathname + url.search, "https://api.acme.dev");
const t0 = Date.now();
const resp = await fetch(new Request(upstream, req));
const out = new Response(resp.body, resp);
const customer = resp.headers.get("x-msa-customer-id") || "anonymous";
out.headers.delete("x-msa-customer-id");
ctx.waitUntil(Promise.resolve(env.EVENTS.writeDataPoint({
blobs: [req.method, url.pathname.replace(/\/\d+/g, "/:id"), customer],
doubles: [resp.status, Date.now() - t0],
indexes: [customer],
})));
return out;
},
};
Then you'll still need: endpoint normalization beyond numeric IDs (UUIDs, slugs), hashing API keys instead of storing them, refusing traffic for origins you don't own, a query layer for the dashboard, and a plan for what happens when storage limits are hit. API Meter handles those for you.
Trade-offs to know
- Latency: a proxy adds a network hop. In our own test from one location it added about 3.4 ms at the median; your numbers will depend on where your origin and users are.
- Availability: the proxy is in the request path, so keep a way to fall back to your origin.
- Cloudflare's built-in tools: if you already proxy your domain through Cloudflare, Endpoint Management shows per-endpoint counts and latency; per-customer breakdowns aren't included below Enterprise (checked Oct 11, 2026).
- Early access: API Meter currently caps capture at about 1,000 events/day; traffic is always forwarded.
Try it
Start free, no SDK See the live demo
Related: Per-customer API analytics · Docs · Pricing comparison