Use these examples to verify incoming webhook payloads before processing.

Verification requirements

  • Read the raw request body bytes exactly as received.
  • Extract X-Hub-Signature-256 header value.
  • Header format must start with sha256=.
  • Compare signatures using constant-time comparison.

Node.js

import crypto from 'crypto';

function verifyMetaSignature(rawBodyBuffer, signatureHeader, appSecret) {
  if (!signatureHeader || !signatureHeader.startsWith('sha256=')) {
    return false;
  }

  const receivedHex = signatureHeader.slice(7);
  const expectedHex = crypto
    .createHmac('sha256', appSecret)
    .update(rawBodyBuffer)
    .digest('hex');

  const received = Buffer.from(receivedHex, 'hex');
  const expected = Buffer.from(expectedHex, 'hex');

  if (received.length !== expected.length) {
    return false;
  }

  return crypto.timingSafeEqual(received, expected);
}

Failure handling

  • Return 403 when signature is invalid.
  • Return 400 for malformed payload.
  • Return 200 quickly for duplicates after dedupe check.
Do not verify signatures on re-encoded JSON. Always verify using raw body bytes from HTTP request.