Skip to content
GreenSnippets

Verify a webhook HMAC signature in Python

Validate a signed webhook body with hmac.compare_digest and a timestamp tolerance.

Python
import hashlib
import hmac
import time


def verify_webhook(raw_body: bytes, timestamp: str, signature_hex: str, secret: str, tolerance: int = 300) -> bool:
    try:
        sent_at = int(timestamp)
    except ValueError:
        return False
    if abs(time.time() - sent_at) > tolerance:
        return False
    message = timestamp.encode() + b"." + raw_body
    expected = hmac.new(secret.encode(), message, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature_hex.lower())

How it works

Sign timestamp + "." + raw_body on the sender side, and verify it the same way. hmac.compare_digest compares in constant time. Rejecting timestamps outside a short window stops an attacker replaying a captured request later.

Always verify against the raw bytes received, before any JSON parsing or re-serialization. The exact header format varies by provider, so follow your provider's documentation.