Skip to main content

A simple local webhook receiver and relay tool

Project description

fasthook 🪝

A dead-simple local webhook receiver for testing and development. Because sometimes you just need to see what's being sent to your endpoint.

PyPI Version PyPI Downloads License GitHub Repo

pip install fasthook
fasthook listen 3000

That's it. You're now catching webhooks on http://localhost:3000.

Why?

You know that moment when you're integrating a third-party service and you need to see what they're actually sending to your webhook? Or when you're testing a payment provider's IPN callbacks locally? Yeah, that's what this is for.

No tunnels, no forwarding services, no accounts. Just a local server that shows you everything that hits it.

Installation

pip install fasthook

Requires Python 3.8 or higher.

Quick Start

Start listening on port 3000:

fasthook listen 3000

Now any request to http://localhost:3000/* will be captured and displayed in your terminal.

Features

See everything: Method, path, headers, query params, body (JSON or raw)

Save to file: Log all events to a JSON file for later analysis

Forward requests: Relay incoming webhooks to another URL (like your actual endpoint)

Pretty output: Optional pretty-printed JSON for easier reading

Quiet mode: Suppress output when you just want to save/forward

Usage Examples

Basic listening:

fasthook listen 3000

Save all events to a file:

fasthook listen 3000 --save events.json

Forward to your actual endpoint:

fasthook listen 3000 --forward http://example.com/webhook

Do everything at once:

fasthook listen 3000 --save events.json --forward http://example.com/webhook --pretty

Bind to a different host:

fasthook listen 3000 --host 0.0.0.0

Run quietly (only show errors):

fasthook listen 3000 --save events.json --quiet

What You'll See

When a webhook hits your endpoint, you'll see something like this:

============================================================
[2025-01-15T10:30:45.123Z] POST /webhook/stripe
IP: 192.168.1.100
Query: {'test': 'true'}
Headers:
  content-type: application/json
  user-agent: Stripe/1.0
  stripe-signature: t=123456,v1=abcdef...
JSON Body:
{
  "id": "evt_123",
  "type": "payment_intent.succeeded",
  "data": {
    "object": {
      "id": "pi_123",
      "amount": 2000,
      "currency": "usd"
    }
  }
}
============================================================

Command Options

fasthook listen PORT [OPTIONS]

Arguments:
  PORT                  Port number to listen on (required)

Options:
  --save PATH          Save events to a JSON file (newline-delimited)
  --forward URL        Forward all requests to this URL
  --pretty             Pretty-print JSON output to console
  --quiet              Suppress console output (except errors)
  --host HOST          Host to bind to (default: 127.0.0.1)
  --debug              Run in debug mode
  --help               Show help message

Saved Events Format

When using --save, events are saved as newline-delimited JSON. Each line is a complete event:

{"timestamp": "2025-01-15T10:30:45.123Z", "method": "POST", "path": "/webhook", "headers": {...}, "query": {...}, "json": {...}, "raw": "", "ip": "192.168.1.100"}

This format is easy to parse and works great with tools like jq:

# Pretty print all events
cat events.json | jq '.'

# Filter POST requests only
cat events.json | jq 'select(.method == "POST")'

# Count events by path
cat events.json | jq -r '.path' | sort | uniq -c

Testing

We use pytest with full async support. The test suite has 100% success rate with 98% code coverage.

Run tests:

pytest

Development

# Clone the repo
git clone https://github.com/Jermy-tech/fasthook.git
cd fasthook

# Install in development mode
pip install -e .

# Run fasthook
fasthook listen 3000

Common Use Cases

Testing Stripe webhooks locally:

fasthook listen 3000 --save stripe-events.json --pretty

Debugging third-party API callbacks:

fasthook listen 8080 --forward http://localhost:5000/api/callback

Recording webhook payloads for documentation:

fasthook listen 3000 --save examples.json --pretty

Running a mock webhook endpoint in CI/CD:

fasthook listen 9000 --quiet --save test-webhooks.json

How It Works

fasthook is built on FastAPI and Uvicorn. It creates a catch-all route that accepts any HTTP method on any path, logs the request details, and optionally saves or forwards the data.

The server runs asynchronously, so it can handle multiple concurrent requests without blocking. When forwarding is enabled, requests are relayed with the same method, headers, and body (minus the host header).

License

MIT License - see LICENSE file for details.

Contributing

Found a bug? Want a feature? Pull requests are welcome!

Author

Built by Jermy Pena

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fasthook-1.0.2.tar.gz (12.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fasthook-1.0.2-py3-none-any.whl (9.0 kB view details)

Uploaded Python 3

File details

Details for the file fasthook-1.0.2.tar.gz.

File metadata

  • Download URL: fasthook-1.0.2.tar.gz
  • Upload date:
  • Size: 12.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.0

File hashes

Hashes for fasthook-1.0.2.tar.gz
Algorithm Hash digest
SHA256 22ca8f5bf05417f6af02624d8fc4bc0ef1354af497ceffb946072a81ee38758a
MD5 bd621d0ccf6f9bcbd4d179879eb50d23
BLAKE2b-256 0c48ae6b89c482db2cd463c0c1801e1d6728aaf4b619eb057993f55139226890

See more details on using hashes here.

File details

Details for the file fasthook-1.0.2-py3-none-any.whl.

File metadata

  • Download URL: fasthook-1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 9.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.0

File hashes

Hashes for fasthook-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 4e86587edfc19e604f60cf5cac6a90387868a24b73a3b379237791f2e39b0df5
MD5 49603dc985bf1df4ee8ac77207056aef
BLAKE2b-256 5e801f4d7da602569273509eafd2ce131a420b49dea9cf7110ce4ba6fc91bae5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page