Verify a webhook HMAC signature in Python
Validate a signed webhook body with hmac.compare_digest and a timestamp tolerance.
- Python
- GreenSnippets
- MIT
- Executed with Python 3.11
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.
Related snippets
- PHP Tested
Validate emails and URLs in PHP
Use filter_var to validate email addresses and http(s) URLs, with an allow-list for schemes.
- Python Tested
Sign API requests with HMAC-SHA256
Create and verify a timestamped signature over the method, path and body so requests cannot be forged or replayed.
- JavaScript Tested
Generate secure random IDs and integers
Create UUIDs, random integers in a range and URL-safe tokens with the Web Crypto API instead of Math.random.
- PHP Tested
Generate a secure random token in PHP
Create unpredictable tokens for password resets, API keys and CSRF protection with random_bytes.

