WhatsApp Cloud API webhook verification not reaching my Worker
Hey all!
I’m trying to set up a WhatsApp Cloud API webhook with a Cloudflare Worker, but Meta’s verification request never seems to hit my Worker.
What I did:
In Meta Developer Dashboard → WhatsApp → Configuration, I set:
Callback URL: https://jolly-darkness-c35f.andrastothbalint.workers.dev/
Verify Token: abc
My Worker code is just a minimal verifier (hard-coded token for now).
I deployed the Worker and confirmed it’s live.
What I saw:
When I click Verify and Save in Meta, I get the error:
“The callback URL or verify token couldn’t be validated.”
In Cloudflare → Workers → Logs → Live, no requests appear when Meta tries to verify.
If I use webhook.site as the callback URL instead, I do see Meta send a proper GET with hub.mode=subscribe, hub.verify_token=abc, and hub.challenge=....
So Meta is definitely sending the request, but Cloudflare Worker doesn’t show anything.
Also noticed this error in the Cloudflare dashboard occasionally:
API Request Failed: GET /api/v4/accounts/.../workers/domains/records (502)
Question:
Has anyone here successfully verified a WhatsApp Cloud API webhook on a Cloudflare Worker? Could Cloudflare be blocking Facebook’s verification requests (Bot Fight Mode, WAF, IPv6 issues)? Any known workarounds or settings I should tweak?
Thanks a ton!!!
1 Reply
Here's my code:
export default {
async fetch(request) {
const url = new URL(request.url);
// Webhook verification (GET)
if (request.method === 'GET') {
const mode = url.searchParams.get('hub.mode');
const token = url.searchParams.get('hub.verify_token');
const challenge = url.searchParams.get('hub.challenge');
if (mode === 'subscribe' && token === 'abc') {
return new Response(challenge, { status: 200 });
} else {
return new Response('Forbidden', { status: 403 });
}
}
// Incoming events (POST)
if (request.method === 'POST') {
const body = await request.json();
console.log("📩 Incoming webhook:", JSON.stringify(body));
return new Response('ok', { status: 200 });
}
return new Response('ok', { status: 200 });
}
}