René's URL Explorer Experiment


Title: Verify an HMAC webhook signature in Python

Open Graph Title: Verify an HMAC webhook signature in Python

X Title: Verify an HMAC webhook signature in Python

Description: Verify HMAC-SHA256 webhook signatures in Python: raw body, v1= list, constant-time compare, 5-minute tolerance. Tested code.

Open Graph Description: Verify HMAC-SHA256 webhook signatures in Python: raw body, v1= list, constant-time compare, 5-minute tolerance. Tested code.

X Description: Verify HMAC-SHA256 webhook signatures in Python: raw body, v1= list, constant-time compare, 5-minute tolerance. Tested code.

Mail addresses
contact@urlpipe.dev

Opengraph URL: https://urlpipe.dev/code/python/verify-webhook

direct link

Domain: urlpipe.dev


Hey, it has json ld scripts:
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://urlpipe.dev/#organization","name":"URLpipe","url":"https://urlpipe.dev","logo":"https://urlpipe.dev/icon.png","sameAs":["https://github.com/URLpipe"],"founder":{"@type":"Person","name":"Roger Campos","url":"https://rogercampos.com"}},{"@type":"WebSite","@id":"https://urlpipe.dev/#website","url":"https://urlpipe.dev","name":"URLpipe","publisher":{"@id":"https://urlpipe.dev/#organization"}}]}
{"@context":"https://schema.org","@graph":[{"@type":"TechArticle","@id":"https://urlpipe.dev/code/python/verify-webhook#article","headline":"Verify an HMAC webhook signature in Python","description":"Verify HMAC-SHA256 webhook signatures in Python: raw body, v1= list, constant-time compare, 5-minute tolerance. Tested code.","url":"https://urlpipe.dev/code/python/verify-webhook","mainEntityOfPage":"https://urlpipe.dev/code/python/verify-webhook","datePublished":"2026-09-24","dateModified":"2026-09-24","author":{"@type":"Person","name":"Roger Campos","url":"https://rogercampos.com"},"publisher":{"@id":"https://urlpipe.dev/#organization"},"image":"https://urlpipe.dev/og-image.png"},{"@type":"FAQPage","mainEntity":[{"@type":"Question","name":"Why verify against the raw body?","acceptedAnswer":{"@type":"Answer","text":"The signature covers the exact bytes that were sent. Parsing the JSON and serializing it again changes key order and whitespace, and the HMAC with them. In Python: request.get_data() in Flask or request.body in Django."}},{"@type":"Question","name":"Why can the signature header hold more than one value?","acceptedAnswer":{"@type":"Answer","text":"During a secret rotation every delivery is signed with the new and the old secret for 24 hours, so a receiver holding either one keeps verifying. Accept the delivery if any v1= value matches."}},{"@type":"Question","name":"What should a receiver answer when the check fails?","acceptedAnswer":{"@type":"Answer","text":"A 401. The delivery is retried with backoff, up to six attempts, and the result stays available from GET /result/:token for 30 days either way."}},{"@type":"Question","name":"Why a five-minute tolerance?","acceptedAnswer":{"@type":"Answer","text":"The timestamp is signed, so it cannot be changed; rejecting old ones stops a captured delivery being replayed later. Every retry is signed afresh, so genuine retries pass."}}]},{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://urlpipe.dev/"},{"@type":"ListItem","position":2,"name":"Code recipes","item":"https://urlpipe.dev/code"},{"@type":"ListItem","position":3,"name":"Python","item":"https://urlpipe.dev/code/python"},{"@type":"ListItem","position":4,"name":"Verify a webhook signature in Python","item":"https://urlpipe.dev/code/python/verify-webhook"}]},{"@type":"HowTo","name":"Verify a webhook signature in Python","description":"To verify a URLpipe webhook in Python, compute HMAC-SHA256 over the X-URLpipe-Timestamp value, a dot and the raw request body, keyed with your whsec_ secret. Prefix it with v1= and compare it with hmac.compare_digest against each comma-separated value of X-URLpipe-Signature; reject timestamps more than five minutes off.","url":"https://urlpipe.dev/code/python/verify-webhook","tool":[{"@type":"HowToTool","name":"Python 3.9+"}],"step":[{"@type":"HowToStep","name":"Before you start","text":"Nothing to install: the receiver below is standard library only. Turn signing on under Settings → Webhook Signing and copy the secret (it starts with whsec_).","url":"https://urlpipe.dev/code/python/verify-webhook#setup"},{"@type":"HowToStep","name":"A receiver that verifies every delivery","text":"verify() is the part to copy into your app. In Flask pass it request.get_data(), in Django request.body — the raw bytes, never request.json re-serialized. hmac.compare_digest takes the same time whether the first byte or the last one differs, which is what stops a timing attack.","url":"https://urlpipe.dev/code/python/verify-webhook#receiver"}]}]}

view-transitionsame-origin
csrf-paramauthenticity_token
csrf-tokenzgMTV2M2awBfp99Y3CYO-Kmgo7WLPXbvFzKcS_A17_YG_pbkNGCt7usPj3c443suxBWx-4e4sdsdaMpcnxngfA
csp-nonce5f5e5339f2567895688f302e693131bc
og:typewebsite
og:site_nameURLpipe
og:localeen_US
og:imagehttps://urlpipe.dev/og-image.png
og:image:width1200
og:image:height630
og:image:altURLpipe — URL in. Clean data out.
twitter:cardsummary_large_image
twitter:imagehttps://urlpipe.dev/og-image.png
twitter:image:altURLpipe — URL in. Clean data out.
theme-color#3b82f6

Links:

Skip to main contenthttps://urlpipe.dev/code/python/verify-webhook#main
URLpipehttps://urlpipe.dev/
Web scraping APIhttps://urlpipe.dev/web-scraping-api
URL to Markdown APIhttps://urlpipe.dev/url-to-markdown-api
MCP serverhttps://urlpipe.dev/mcp-server
Screenshot APIhttps://urlpipe.dev/screenshot-api
Lighthouse APIhttps://urlpipe.dev/lighthouse-api
Metadata APIhttps://urlpipe.dev/metadata-api
Console APIhttps://urlpipe.dev/console-api
Rendered HTML APIhttps://urlpipe.dev/rendered-html-api
URL to PDF APIhttps://urlpipe.dev/url-to-pdf-api
Website technology lookup APIhttps://urlpipe.dev/website-technology-lookup-api
Structured data extraction APIhttps://urlpipe.dev/structured-data-extraction-api
Keyword extraction APIhttps://urlpipe.dev/keyword-extraction-api
URL summarization APIhttps://urlpipe.dev/url-summarization-api
Web access for AI agentshttps://urlpipe.dev/use-cases/ai-agents
Web pages into a RAG pipelinehttps://urlpipe.dev/use-cases/rag-ingestion
Link previews and unfurlshttps://urlpipe.dev/use-cases/link-previews
Monitoring client websiteshttps://urlpipe.dev/use-cases/client-site-monitoring
Monitoring pages for changeshttps://urlpipe.dev/use-cases/content-monitoring
Archiving pages as screenshotshttps://urlpipe.dev/use-cases/visual-archiving
URL features inside a multi-tenant apphttps://urlpipe.dev/use-cases/multi-tenant-apps
Free toolshttps://urlpipe.dev/tools
Docshttps://urlpipe.dev/docs
Pricinghttps://urlpipe.dev/pricing
Guideshttps://urlpipe.dev/guides
Code recipeshttps://urlpipe.dev/code
Glossaryhttps://urlpipe.dev/glossary
Researchhttps://urlpipe.dev/research
Comparehttps://urlpipe.dev/compare
Changeloghttps://urlpipe.dev/changelog
Engineering noteshttps://urlpipe.dev/notes
Sign inhttps://urlpipe.dev/auth/session/new
Start freehttps://urlpipe.dev/auth/sign-up/new
Web scraping APIhttps://urlpipe.dev/web-scraping-api
URL to Markdown APIhttps://urlpipe.dev/url-to-markdown-api
MCP serverhttps://urlpipe.dev/mcp-server
Screenshot APIhttps://urlpipe.dev/screenshot-api
Lighthouse APIhttps://urlpipe.dev/lighthouse-api
Metadata APIhttps://urlpipe.dev/metadata-api
Console APIhttps://urlpipe.dev/console-api
Rendered HTML APIhttps://urlpipe.dev/rendered-html-api
URL to PDF APIhttps://urlpipe.dev/url-to-pdf-api
Website technology lookup APIhttps://urlpipe.dev/website-technology-lookup-api
Structured data extraction APIhttps://urlpipe.dev/structured-data-extraction-api
Keyword extraction APIhttps://urlpipe.dev/keyword-extraction-api
URL summarization APIhttps://urlpipe.dev/url-summarization-api
Web access for AI agentshttps://urlpipe.dev/use-cases/ai-agents
Web pages into a RAG pipelinehttps://urlpipe.dev/use-cases/rag-ingestion
Link previews and unfurlshttps://urlpipe.dev/use-cases/link-previews
Monitoring client websiteshttps://urlpipe.dev/use-cases/client-site-monitoring
Monitoring pages for changeshttps://urlpipe.dev/use-cases/content-monitoring
Archiving pages as screenshotshttps://urlpipe.dev/use-cases/visual-archiving
URL features inside a multi-tenant apphttps://urlpipe.dev/use-cases/multi-tenant-apps
Free toolshttps://urlpipe.dev/tools
Docshttps://urlpipe.dev/docs
Pricinghttps://urlpipe.dev/pricing
Guideshttps://urlpipe.dev/guides
Code recipeshttps://urlpipe.dev/code
Glossaryhttps://urlpipe.dev/glossary
Researchhttps://urlpipe.dev/research
Comparehttps://urlpipe.dev/compare
Changeloghttps://urlpipe.dev/changelog
Engineering noteshttps://urlpipe.dev/notes
Start freehttps://urlpipe.dev/auth/sign-up/new
Sign inhttps://urlpipe.dev/auth/session/new
Roger Camposhttps://rogercampos.com
Start freehttps://urlpipe.dev/auth/sign-up/new
See the APIhttps://urlpipe.dev/#endpoints
shell script on the cURL pagehttps://urlpipe.dev/code/curl/verify-webhook
Client libraries in the docshttps://urlpipe.dev/docs/client-libraries
Python client on GitHubhttps://github.com/URLpipe/urlpipe-python
Node.jshttps://urlpipe.dev/code/node/verify-webhook
PHPhttps://urlpipe.dev/code/php/verify-webhook
Rubyhttps://urlpipe.dev/code/ruby/verify-webhook
Gohttps://urlpipe.dev/code/go/verify-webhook
Javahttps://urlpipe.dev/code/java/verify-webhook
C#https://urlpipe.dev/code/csharp/verify-webhook
cURLhttps://urlpipe.dev/code/curl/verify-webhook
every Python recipehttps://urlpipe.dev/code/python
how signing works, in the docshttps://urlpipe.dev/docs/async#signature
Check whether robots.txt lets a bot fetch a URLhttps://urlpipe.dev/tools/robots-txt-checker
Get the rendered HTML of a JavaScript page in cURLhttps://urlpipe.dev/code/curl/rendered-html
Per-project rate limitshttps://urlpipe.dev/changelog/per-project-rate-limits
Get the rendered HTML of a JavaScript page in C#https://urlpipe.dev/code/csharp/rendered-html
Close your account or delete an organization yourselfhttps://urlpipe.dev/changelog/account-and-organization-deletion
HTMLhttps://urlpipe.dev/docs/html
All of code recipeshttps://urlpipe.dev/code
Start freehttps://urlpipe.dev/auth/sign-up/new
URLpipehttps://urlpipe.dev/
Web scraping APIhttps://urlpipe.dev/web-scraping-api
URL to Markdown APIhttps://urlpipe.dev/url-to-markdown-api
MCP serverhttps://urlpipe.dev/mcp-server
Screenshot APIhttps://urlpipe.dev/screenshot-api
Lighthouse APIhttps://urlpipe.dev/lighthouse-api
Metadata APIhttps://urlpipe.dev/metadata-api
Console APIhttps://urlpipe.dev/console-api
Rendered HTML APIhttps://urlpipe.dev/rendered-html-api
URL to PDF APIhttps://urlpipe.dev/url-to-pdf-api
Website technology lookup APIhttps://urlpipe.dev/website-technology-lookup-api
Structured data extraction APIhttps://urlpipe.dev/structured-data-extraction-api
Keyword extraction APIhttps://urlpipe.dev/keyword-extraction-api
URL summarization APIhttps://urlpipe.dev/url-summarization-api
Free toolshttps://urlpipe.dev/tools
Pricinghttps://urlpipe.dev/pricing
Docshttps://urlpipe.dev/docs
Client librarieshttps://urlpipe.dev/docs/client-libraries
Guideshttps://urlpipe.dev/guides
Code recipeshttps://urlpipe.dev/code
Use caseshttps://urlpipe.dev/use-cases
Integrationshttps://urlpipe.dev/integrations
Glossaryhttps://urlpipe.dev/glossary
Researchhttps://urlpipe.dev/research
Engineering noteshttps://urlpipe.dev/notes
Changeloghttps://urlpipe.dev/changelog
llms.txthttps://urlpipe.dev/llms.txt
All comparisonshttps://urlpipe.dev/compare
URLpipe vs Firecrawlhttps://urlpipe.dev/compare/urlpipe-vs-firecrawl
URLpipe vs Jina Readerhttps://urlpipe.dev/compare/urlpipe-vs-jina-reader
Best HTML-to-Markdown APIshttps://urlpipe.dev/best-html-to-markdown-apis
Jina Reader alternativeshttps://urlpipe.dev/alternatives/jina-reader
Microlink alternativeshttps://urlpipe.dev/alternatives/microlink
ScreenshotOne alternativeshttps://urlpipe.dev/alternatives/screenshotone
Abouthttps://urlpipe.dev/about
Securityhttps://urlpipe.dev/security
Statushttps://urlpipe.dev/status
GitHubhttps://github.com/URLpipe
Privacyhttps://urlpipe.dev/privacy
Termshttps://urlpipe.dev/terms
Sign inhttps://urlpipe.dev/auth/session/new
Legal noticehttps://urlpipe.dev/terms#legal-notice
Roger Camposhttps://rogercampos.com

Viewport: width=device-width,initial-scale=1


URLs of crawlers that visited me.