Test a GitHub webhook

Test a GitHub webhook, without deploying.

Paste a Tracehook capture URL as a GitHub webhook's Payload URL and read the event exactly as GitHub sends it: X-GitHub-Event, X-GitHub-Delivery, X-Hub-Signature-256 and the full body, live. No account, encrypted, erased after 24 h.

  • X-GitHub-Event
  • X-GitHub-Delivery
  • X-Hub-Signature-256
  • Content-Type

Where to paste the URL

Four steps, no server-side configuration. Replace ‹domain› and ‹your-id› with your session's values.

  1. 1

    Create a capture URL (button below). You get an address of the form https://<domain>/h/<your-id>. You can add a sub-path, e.g. /github.

  2. 2

    On GitHub, open your repository → Settings → Webhooks → "Add webhook" (same path at the organization level).

  3. 3

    Paste the capture URL into "Payload URL". Choose "Content type: application/json", fill in a "Secret" if you want to test the signature, then the events to receive.

  4. 4

    Save: GitHub immediately sends a ping event. It appears in your Tracehook session; every push, pull request or issue follows.

What the received request looks like

The headers below are the ones GitHub documents on every delivery. Tracehook shows them in the order received, with the raw body.

X-GitHub-Event

Event type: ping, push, pull_request, issues, …

X-GitHub-Delivery

Unique delivery identifier (GUID), also visible in "Recent Deliveries".

X-Hub-Signature-256

sha256=<HMAC-SHA256 of the raw body with your secret>. Present only if a secret is configured.

Content-Type

application/json if you chose it; otherwise application/x-www-form-urlencoded with the JSON in a payload field.

Body shape (example, fake values)
{
  "zen": "…",
  "hook_id": 123456789,
  "hook": {
    "type": "Repository",
    "id": 123456789,
    "events": ["push", "pull_request"],
    "config": { "content_type": "json", "url": "https://<domain>/h/<your-id>/github" }
  },
  "repository": { "full_name": "org/repo", "…": "…" },
  "sender": { "login": "…", "…": "…" }
}

Common pitfalls

What explains most of the "my webhook isn't arriving" or "invalid signature" reports.

Default content type: form-encoded

By default GitHub sends application/x-www-form-urlencoded with the JSON in a payload field. If your handler expects raw JSON, choose "application/json" in the webhook configuration. Tracehook shows both forms (Body and Raw tabs).

Signature on the raw body

X-Hub-Signature-256 is computed on the exact bytes of the body. Compare with a constant-time function and without re-serializing the JSON. The raw body is available in the Raw tab.

No secret, no signature

If the "Secret" field is empty, the X-Hub-Signature-256 header is absent. A handler that requires it will error out: fill in the secret or relax the test.

The ping event is not a push

The first event received on creation is ping (X-GitHub-Event: ping). Its body has neither commits nor a ref: don't mistake it for a failed delivery.

Replay from GitHub or from Tracehook

Settings → Webhooks → Recent Deliveries lets you resend a delivery ("Redeliver"). You can also copy the request as cURL from Tracehook and replay it against your local server.

curl example

To check that your capture URL does receive a request of this shape, without waiting for the provider.

curl -X POST https://<domain>/h/<your-id>/github \
  -H 'Content-Type: application/json' \
  -H 'X-GitHub-Event: ping' \
  -H 'X-GitHub-Delivery: 72d3162e-cc78-11e3-81ab-4c9367dc0958' \
  -H 'X-Hub-Signature-256: sha256=<fake-signature>' \
  -d '{"zen":"Keep it logically awesome.","hook_id":123456789,"repository":{"full_name":"org/repo"}}'

This command mimics the shape of a GitHub ping event (fake values, invalid signature). For a real signed event, go through the repository configuration.

Limits to know

One value, everywhere.

  • 50last requests per session
  • 1 MiBper request, headers included (413 beyond that)
  • 24 hof inactivity, then everything is erased

Details on encryption and retention: Security. Routes, SSE stream and error codes: API reference. Other provider: test a Stripe webhook.

Your next GitHub webhook — you'll read it live.

No sign-up