How to get a free webhook URL for testing (no signup)
Open view.webhooks.page or run curl -X POST https://webhooks.sh/v1/bins to get a public HTTPS webhook URL that captures every request: method, headers and body. Free, no signup. Any method and path, 100KB bodies, 100 requests a day, 48 hours unless claimed.
You don't need an account, a server or a tunnel to get a webhook URL for testing. A bin on webhooks.sh is a temporary webhook receiver: a public HTTPS endpoint that records every request it gets and lets you read them back in the browser or over HTTP.
The 10-second way: in the browser
- Open view.webhooks.page and create a bin. There's a quick human check; no email, password or card.
- Copy the webhook URL. It looks like
https://7c2e9f4a1b8d4e3f9a6c0d5b2e8f1a47.webhooks.page/. - Save the view URL and the claim URL shown with it: they're displayed once and can't be recovered.
- Paste the webhook URL wherever the sender asks for one, open the viewer, and trigger an event.
The one-command way: curl
curl -X POST https://webhooks.sh/v1/bins
No API key, no request body. The reply is 201 Created with JSON like this (trimmed):
{
"bin": "7c2e9f4a1b8d4e3f9a6c0d5b2e8f1a47",
"ingest_url": "https://7c2e9f4a1b8d4e3f9a6c0d5b2e8f1a47.webhooks.page/",
"view_url": "https://view.webhooks.page/b/7c2e9f4a1b8d4e3f9a6c0d5b2e8f1a47#3b9d7e1f5a2c8e4d6b0f9a1c7e3d5b28",
"claim_url": "https://webhooks.sh/claim/7c2e9f4a1b8d4e3f9a6c0d5b2e8f1a47#key=e6a1c4f8b2d9e7a3c5f0b8d1a4e6c9f2",
"expires_at": "2026-10-03T09:14:07.000Z"
}
ingest_urlis your webhook URL; give it to the sender. It's write-only: it lets someone send requests to the bin, not read them.view_urlopens the live viewer. The part after#is the view key, the read credential for the viewer and the API. Anyone with the full view URL can read the bin, and a lost key can't be recovered.claim_urlis a one-time link that keeps the bin past 48 hours. Treat it like a password.
Send a test request
Any HTTP client will do. With curl:
curl -X POST "https://7c2e9f4a1b8d4e3f9a6c0d5b2e8f1a47.webhooks.page/orders?source=test" \
-H "Content-Type: application/json" \
-d '{"event":"order.created","order_id":"ord_123"}'
The bin replies with 200 and a delivery ID:
{"ok":true,"delivery_id":"5f0c2a9e-3b7d-4e1a-9c6f-8d2b4a7e1c03"}
The same ID is in the x-webhooks-delivery response header, and it's how you fetch this exact request from the API.
Watch it arrive
Open the view URL. Each request shows its method, path, query string, headers, body and timestamp, and the page updates live while it's open. Requests appear within about a second, bursts included.
Read captured requests over HTTP
Everything in the viewer is also available as JSON from view.webhooks.page. Send the view key in an x-view-key header:
BIN=7c2e9f4a1b8d4e3f9a6c0d5b2e8f1a47
KEY=3b9d7e1f5a2c8e4d6b0f9a1c7e3d5b28
ID=5f0c2a9e-3b7d-4e1a-9c6f-8d2b4a7e1c03 # the delivery_id from the reply
# Latest 10 requests, newest first
curl -H "x-view-key: $KEY" https://view.webhooks.page/api/bins/$BIN/deliveries
# One request, with headers and the body as base64
curl -H "x-view-key: $KEY" https://view.webhooks.page/api/bins/$BIN/deliveries/$ID
# The raw body bytes, exactly as sent
curl -H "x-view-key: $KEY" -o body.bin \
https://view.webhooks.page/api/bins/$BIN/deliveries/$ID/body
Each entry in the list looks like this:
{
"id": "5f0c2a9e-3b7d-4e1a-9c6f-8d2b4a7e1c03",
"received_at": "2026-10-01T09:14:12.481Z",
"method": "POST",
"path": "/orders",
"query": "?source=test",
"size_bytes": 46,
"truncated": false,
"content_type": "application/json",
"remote_ip": "203.0.113.7"
}
The single-request call adds headers and body_base64; a wrong or missing key gets 403 with code invalid_view_key. The raw download gives you the exact bytes the provider signed, which is what you need to check a signature with the HMAC signature verifier or to replay the request against your own handler with curl --data-binary @body.bin.
What the URL accepts
- Any method. POST, PUT, PATCH, DELETE, GET, HEAD and OPTIONS are all recorded. Browser CORS preflights and favicon fetches get an answer but aren't recorded or counted.
- Any path and query string.
/stripe,/github/push?attempt=2and plain/all land in the same bin with the path kept, so one bin can serve several senders. - Any content type. JSON, form-encoded, XML, plain text or binary, stored byte for byte.
- Bodies up to 100KB. Anything larger gets
413with codebody_too_largeand isn't recorded. - 100 requests a day per bin. Past that the URL answers
429with codedaily_cap_reachedand aRetry-Afterheader until the count resets at midnight UTC. - One fixed reply. Every accepted request gets
200and the JSON above; the status code, headers and body can't be changed.
How long it lasts, and how to keep it
An unclaimed bin lasts 48 hours from creation (see expires_at). After that it stops recording and the view key stops working; the sender may still see a success response for a while, but nothing is saved.
To keep a bin, open its claim_url (or the claim link in the viewer, in the tab where you created it) and sign in with Google: free, about 20 seconds. Claiming:
- stops the 48-hour timer; the webhook URL stays the same, so the sender needs no changes;
- keeps new requests for 30 days, rolling, with the full history in your dashboard;
- isn't retroactive: earlier requests keep their original 48-hour expiry;
- replaces the view key, so an old view URL (say, one an AI agent holds) stops working.
The 100-requests-a-day cap still applies to claimed bins. Named URLs that never expire, higher limits and longer history come with the Solo plan ($12/month) on webhooks.host; see pricing.
Privacy: who can see your requests
- The view key is the only read credential. It sits in the URL fragment after
#, which browsers never send in page requests. - The webhook URL can't read anything. Whoever has it can send requests (and use up your 100 a day), nothing more.
- Secret-looking headers are masked. Any header whose name contains
authorization,cookie,key,tokenorsecretshows as redacted in the viewer and the API (GitLab'sX-Gitlab-Tokenincluded). Signature headers likeStripe-SignatureandX-Hub-Signature-256stay intact so you can verify them. - Bodies are shown as sent. Use test-mode events and fake customer data.
Use it with Stripe, GitHub, Shopify, Slack, Twilio and Discord
Paste the webhook URL wherever the provider asks for an endpoint. Most senders just work, and the bin passes the usual URL verification handshakes on its own (Slack, Meta, Strava, Dropbox, Microsoft Graph, Twitch). Senders that need a specific reply don't:
| Provider | Where the URL goes | With a bin |
|---|---|---|
| Stripe | Webhook endpoint in the Dashboard, test mode | Works. Fire events with stripe trigger payment_intent.succeeded; Stripe-Signature is captured. |
| GitHub | Repo Settings > Webhooks > Add webhook | Works. A ping event arrives on save. Choose application/json; the form option wraps the JSON in a payload field. |
| Shopify | Settings > Notifications > Webhooks | Works, with X-Shopify-Topic and X-Shopify-Hmac-Sha256 intact. |
| Twilio | Status callback, SMS or voice URL | Status callbacks work. SMS and voice requests are captured, but Twilio expects TwiML back, logs error 12300, and a voice call fails. |
| Slack | Event Subscriptions Request URL | Works. The bin echoes the url_verification challenge, so Slack activates the URL and every event after it lands in the bin. |
| Discord | Interactions Endpoint URL | Won't save: Discord first needs a verified reply to its signed PING. Use a bin to inspect what your code posts to a Discord webhook instead. |
No real event yet? Build one with the webhook payload generator and send it to the bin with curl.
Use it in scripts, CI and AI agents
Creating a bin needs no key, so a script, CI job or AI agent can make its own webhook URL and check what arrived:
resp=$(curl -s -X POST https://webhooks.sh/v1/bins)
bin=$(echo "$resp" | jq -r .bin)
key=$(echo "$resp" | jq -r .view_url | cut -d'#' -f2)
# Point the system under test at https://$bin.webhooks.page/ and trigger it
sleep 15
curl -s -H "x-view-key: $key" "https://view.webhooks.page/api/bins/$bin/deliveries" \
| jq '.deliveries[] | {method, path, received_at}'
- Creation limits: 5 bins a minute and 20 a day per IP, then
429with coderate_limitedordaily_capand aRetry-Afterheader. - Errors are JSON (
{"error": "...", "code": "..."}), so scripts can branch oncode. - One bin per run, not per test. Give each test its own path (
/test-refund,/test-signup) and filter onpath. The view-key API lists only the latest 10 requests, so read as you go. - Agents: pass the
claim_urlorclaim_urnto the user privately, never in a public issue or chat log. Claiming replaces the view key the agent holds. Full contract: webhooks.sh/llms.txt.
Limits at a glance
| Limit | Free bin | Past the limit |
|---|---|---|
| Lifetime | 48 hours from creation | Stops recording; claim it (free) to keep it |
| Requests | 100 per bin per day | 429 daily_cap_reached until midnight UTC |
| Body size | 100KB per request | 413 body_too_large, not recorded |
| Readable in the viewer and API | Latest 10 requests | Older ones stay hidden until you claim |
| History after claiming | 30 days, rolling | Older requests roll off |
| Bin creation over the API | 5 a minute, 20 a day per IP | 429 rate_limited or daily_cap |
| Reply to the sender | 200 with fixed JSON | Not configurable |
When you need a different tool
- Your own code has to receive the webhook. A bin is a hosted listener: it records requests but doesn't forward them to your machine. For traffic to localhost you need a tunnel; see testing webhooks locally and testing webhooks without ngrok.
- The sender needs a specific reply. Discord's PING, TwiML for Twilio, or a deliberate
500to test retries all need an endpoint whose response you control: your own handler behind a tunnel, or a mock server. Some hosted request inspectors offer configurable responses; the webhook testing tools comparison is a good place to start. - You need a permanent production endpoint. A bin is for testing; a long-lived URL with delivery guarantees and replay is a webhook gateway's job (see the Hookdeck comparison).
FAQ
Is there a free webhook URL I can use without signing up?
Yes. Open view.webhooks.page or run curl -X POST https://webhooks.sh/v1/bins for a public HTTPS webhook URL, free, with no account, email or card. A free Google sign-in is only needed to claim a bin and keep it past 48 hours.
How do I test a webhook online without writing code?
Create a bin, paste its URL into the provider's webhook settings, trigger an event, and read the method, headers and body in the viewer. You need code only once your own handler has to respond.
How long does a temporary webhook URL last?
48 hours from creation; expires_at has the exact time. Claim the bin to stop the timer and keep the same URL.
Can I get a permanent or custom webhook URL for free?
A claimed bin keeps its random URL with no expiry and a rolling 30-day history, still capped at 100 requests a day. URLs with a name you choose come with the Solo plan ($12/month).
How many requests can the webhook URL receive?
100 per bin per day, each up to 100KB. After that the URL answers 429 daily_cap_reached until midnight UTC; for a bigger test run, create another bin.
Why isn't my request showing up?
Give it a second. Then check that the sender has the webhook URL (https://<bin>.webhooks.page/), not the view URL; that the body is under 100KB; and that the bin is under its daily cap and hasn't expired. If all of that holds, the sender never delivered it to this URL: see the webhook not received guide.
Can I send requests to it from browser JavaScript?
Yes. The bin answers CORS preflights and allows any origin, so a JSON fetch() from a page on another origin goes through and your script can read the reply, including the X-Webhooks-Delivery header. Preflights aren't recorded and don't count toward the daily cap.
Is it safe to send real data to a free webhook URL?
Use test data only: secret-looking headers are masked, but bodies are readable by anyone holding the view URL.
Can an AI agent create a webhook URL for me?
Yes. POST https://webhooks.sh/v1/bins needs no key and returns the webhook URL, the view URL and a claim link to pass on to you. The contract for agents is at webhooks.sh/llms.txt.
What's the difference between a request bin and a tunnel like ngrok?
A request bin (or request catcher) is a hosted URL that stores requests for you to inspect; a tunnel forwards them to a server on your machine. The bin answers "what exactly did the sender send?", the tunnel "does my handler work?". More in the ngrok comparison.
Last updated
Try it in 10 seconds.
Create a free bin at view.webhooks.page — no signup, no install. Point your sender at the URL and watch requests land live. Bins expire after 48 hours.