All Providers
πŸ™

GitHub Webhooks

Developer Tools

GitHub sends webhook events for repository activity: pushes, pull requests, issues, Actions workflow runs, releases, and more. Used for CI/CD triggers, PR bots, and deploy automations.

GitHub repository Settings β†’ Webhooks page showing the Add webhook form with focused empty Payload URL field, content type selector, and event picker for push, pull_request, and issues events.
GitHub dashboard webhook configuration screen β€” schematic showing the empty endpoint URL field, event subscriptions, and primary action button.

Webhook Events

8 event types

push

Commits pushed to a branch

pull_request

PR opened, closed, merged, or reviewed

workflow_run

GitHub Actions workflow completed

issues

Issue opened, closed, or labelled

release

Release published or created

issue_comment

Comment posted on an issue or PR

create

Branch or tag created

star

Repository starred or unstarred

Signature Verification

Header
X-Hub-Signature-256
Method

HMAC-SHA256 of raw body; compare sha256=<hex> to header

View official docs

Sample Payload

push

application/json
{
  "ref": "refs/heads/main",
  "before": "abc1234567890abc",
  "after": "def1234567890def",
  "repository": {
    "id": 123456,
    "name": "my-repo",
    "full_name": "acme/my-repo",
    "private": false
  },
  "pusher": {
    "name": "octocat",
    "email": "[email protected]"
  },
  "commits": [
    {
      "id": "def1234567890def",
      "message": "Fix: webhook signature verification",
      "author": {
        "name": "octocat"
      }
    }
  ]
}

Send a Sample GitHub Payload

Pick an event, enter your endpoint URL (or localhost), and fire a realistic GitHub payload with one click β€” no GitHub account needed.

Test Sender

Loading samples…

No signup

Capture & Inspect GitHub Webhooks Live

Get a free public HTTPS endpoint below, point GitHub at it, and watch events arrive in real time. Use the forwarding rule to relay them straight to your local server.

Live demo β€” no signup required

See it work in real time

Click below to get a live webhook URL instantly. Paste it anywhere β€” Stripe, GitHub, Postman β€” and watch events arrive right here.

Expires in 1 hour Β· No account needed

Forward GitHub webhooks to localhost

  1. Click Create live endpoint above to get a public HTTPS URL
  2. Paste the URL into GitHub's webhook settings
  3. In the Forwarding tab, add a rule: target = http://localhost:3000/webhooks/github
  4. Fire a test event from GitHub β€” it arrives in the inspector and hits your local handler simultaneously

Ready to test your GitHub webhook handler?

Free HTTPS endpoint with forwarding, retry, and event replay. No install, no CLI, no deploy.

Create Free Account

Common GitHub Webhook Errors

HTTP 400 β€” Invalid X-Hub-Signature-256

Cause: The HMAC digest doesn't match. Usually caused by reading a parsed body instead of the raw buffer, or using the wrong secret.

Fix: Use the raw request body bytes for HMAC computation. In Express, apply express.raw() before your route. Double-check the secret matches exactly what's set in GitHub.

Delivery shows "failed" in GitHub UI

Cause: Your endpoint returned a non-2xx status or timed out (GitHub's timeout is 10 seconds).

Fix: Return 200 immediately and process the event asynchronously. Use a queue (e.g. BullMQ, SQS) for heavy processing.

Receiving unexpected event types

Cause: You selected "Send me everything" when creating the webhook.

Fix: Edit the webhook in GitHub β†’ Settings β†’ Webhooks and select only the specific events you need.

Signature Verification Code

Node.js
const crypto = require('crypto');

app.post('/webhooks/github', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-hub-signature-256'];
  const hmac = crypto.createHmac('sha256', process.env.GITHUB_WEBHOOK_SECRET);
  const digest = 'sha256=' + hmac.update(req.body).digest('hex');
  if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(digest))) {
    return res.status(400).send('Invalid signature');
  }
  const event = req.headers['x-github-event'];
  const payload = JSON.parse(req.body);
  // Handle event here
  res.json({ received: true });
});
Python
import hmac, hashlib, os
from flask import Flask, request

app = Flask(__name__)

@app.route('/webhooks/github', methods=['POST'])
def github_webhook():
    sig = request.headers.get('X-Hub-Signature-256', '')
    digest = 'sha256=' + hmac.new(
        os.environ['GITHUB_WEBHOOK_SECRET'].encode(),
        request.get_data(), hashlib.sha256
    ).hexdigest()
    if not hmac.compare_digest(sig, digest):
        return 'Invalid signature', 400
    event = request.headers.get('X-GitHub-Event')
    # Handle event here
    return '', 200
Go
import "crypto/hmac"
import "crypto/sha256"

func verifyGitHub(body []byte, signature, secret string) bool {
    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write(body)
    expected := "sha256=" + hex.EncodeToString(mac.Sum(nil))
    return hmac.Equal([]byte(signature), []byte(expected))
}

How to Test GitHub Webhooks with WebhookWhisper

  1. 1

    Create a free WebhookWhisper endpoint

    Click "Create live endpoint" on this page and copy your HTTPS URL.

  2. 2

    Go to your GitHub repo β†’ Settings β†’ Webhooks

    Click "Add webhook". Paste your WebhookWhisper URL into the Payload URL field.

  3. 3

    Set content type to application/json

    Change Content type to "application/json". Add a secret β€” copy it, you'll need it for signature verification.

  4. 4

    Choose events to receive

    Select individual events (push, pull_request, issues) or "Send me everything" for testing.

  5. 5

    Trigger and inspect

    GitHub sends a ping event immediately. Watch it appear in WebhookWhisper, then forward to your local handler.

GitHub Webhook FAQ

What is X-Hub-Signature-256?

It's the HMAC-SHA256 signature GitHub attaches to every webhook request. Compute the same HMAC on your side using the raw body and your secret, and compare with timing-safe equality.

How do I test GitHub webhooks locally?

Use WebhookWhisper: get a public HTTPS URL, paste it into GitHub's webhook settings, then add a forwarding rule to http://localhost:3000. No ngrok needed.

Can GitHub webhooks send to localhost?

No β€” GitHub requires a publicly accessible HTTPS URL. Use WebhookWhisper as a relay: it receives the event and forwards it to your local server.

How long does GitHub retry failed webhooks?

GitHub retries for up to 3 days. You can also redeliver any event manually from the webhook's Recent Deliveries tab.