https://github.com/clsmedia/kapture
Catch, log, and inspect every HTTP webhook in real time. A minimalist PHP webhook receiver with admin UI, JSONL logs, and zero dependencies.
https://github.com/clsmedia/kapture
debugging-tool http-capture php webhook webhook-inspector webhook-receiver
Last synced: 3 days ago
JSON representation
Catch, log, and inspect every HTTP webhook in real time. A minimalist PHP webhook receiver with admin UI, JSONL logs, and zero dependencies.
- Host: GitHub
- URL: https://github.com/clsmedia/kapture
- Owner: clsmedia
- Created: 2026-05-23T17:03:26.000Z (11 days ago)
- Default Branch: main
- Last Pushed: 2026-05-23T19:09:40.000Z (11 days ago)
- Last Synced: 2026-05-23T19:10:07.004Z (11 days ago)
- Topics: debugging-tool, http-capture, php, webhook, webhook-inspector, webhook-receiver
- Language: PHP
- Homepage:
- Size: 343 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Kapture — PHP Webhook Receiver & Inspector
Catch, log, and inspect every HTTP request — self-hosted, zero dependencies, and yours forever.
[](https://php.net)
[](LICENSE)
[](https://github.com/clsmedia/kapture)

## Why?
Testing webhook integrations is painful. You guess what your service sent, hit F5 a hundred times, and pray the request format is right. **Kapture** gives you a dead-simple endpoint that logs everything — method, headers, body, query params, IP — and lets you inspect it in a clean UI.
But here's the thing about tools like webhook.site and RequestBin: every webhook you send to them **leaves your machine**. Your payloads live on someone else's server, they expire in hours, and if you need to check what Stripe sent you last week — it's gone.
Kapture is self-hosted, open-source, and **persists your logs as long as you need them**. One command and your data stays yours forever. No rate limits, no signup, no "try again tomorrow." Zero dependencies — drop it on any server (even shared hosting) and it just works.
## Quick Start
```bash
php -S 0.0.0.0:8080 -t public
```
Send a webhook:
```bash
curl -X POST -H "Content-Type: application/json" \
-d '{"event":"user.created","email":"user@example.com"}' \
http://localhost:8080/kapture/anything-you-like
```
Open the admin:
```bash
open http://localhost:8080/admin
```
Password: `changeme`
To switch to SQLite storage, set `STORAGE_DRIVER=sqlite` in `.env` (requires `ext-sqlite3`).
## Features
### You own your data
- **Self-hosted** — your webhooks never leave your machine. No third party sees your payloads.
- **Persistent logs** — stays across restarts. Check what Shopify sent you last week? Open the archive.
- **Configurable retention** — keep logs for 7 days or 7 months. Prune when you're ready.
### Drop-dead simple
- **Zero dependencies** — just PHP 8.3+. No Composer install, no database setup, no Docker required.
- **One command to run** — `php -S 0.0.0.0:8080 -t public` and you're capturing.
- **Works everywhere** — laptop, shared hosting, DigitalOcean box, Raspberry Pi.
### Inspect everything
- **Full capture** — headers, body, query params, IP, timestamp, any HTTP method
- **Dark theme admin UI** — expandable details, text filter, group-by-URI-path, live auto-refresh
- **Archive browser** — pick any daily log from the sidebar. Browse tomorrow what came in today.
- **Raw dump** — `?raw` for JSONL access. Pipe into `jq`, grep, or your own tooling.
### Flexible storage
- **JSONL files** — one JSON object per line, standard format, readable by any tool
- **SQLite option** — set `STORAGE_DRIVER=sqlite` for a single database file
- **Daily rotation** — automatic, with configurable pruning
## What makes Kapture different
- **Self-hosted** — no third-party server sees your payloads
- **Persistent logs** — stays across restarts, browsable by day, configurable retention
- **Zero dependencies** — just PHP. No Composer, no Docker, no database setup
- **No rate limits, no signup** — run it, use it, done
- **Runs anywhere** — laptop, shared hosting, VPS, Raspberry Pi
## Usage
### Webhook endpoint
```
POST /kapture/your-custom-path
GET /kapture/anything?foo=bar
PUT /kapture/test
...
```
Returns `{"ok":true,"uid":""}`. Keep the capture ID to find it in the logs.
### Admin panel
| URL | What |
|---|---|
| `/admin` | UI — browse, filter, expand requests |
| `/admin?raw` | Raw JSONL dump of today's file |
| `/admin?file=2026-05-23` | Browse a specific day's log |
| `/admin?file=2026-05-23&raw` | Raw dump of a specific day |
## Configuration
Copy `.env.example` → `.env` and edit — the app won't start without it:
```bash
ADMIN_PASSWORD=changeme # Admin login password
LOG_DIR=./logs # Where logs / database are stored
ROTATE_DAYS=7 # Days to keep logs (filesystem only)
STORAGE_DRIVER=filesystem # 'filesystem' (default) or 'sqlite'
```
## Log Format
Each request is logged as a single JSON line (JSONL):
```json
{
"capturedAt": "2026-05-23T14:30:00Z",
"method": "POST",
"uri": "/kapture/orders",
"query": {"source": "shopify"},
"headers": {
"Content-Type": "application/json",
"User-Agent": "Shopify-Captain-Hook/1.0"
},
"body": "{\"event\":\"order.created\"}",
"ip": "203.0.113.42",
"captureId": "a1b2c3d4e5f6g7h8"
}
```
## Requirements
- PHP 8.3+
## Development
```bash
php -S 0.0.0.0:8080 -t public
```
The built-in server handles routing. No Apache or Nginx needed.
### Testing
```bash
composer test
```
### Code quality
```bash
composer check # phpstan + ecs + tests
composer ecs:fix # auto-fix code style
```
- **PHPStan** — static analysis at level 8
- **ECS** — PSR-12 code style with Symfony rules
- **PHPUnit**
## FAQ
**Does it work with Stripe / Shopify / GitHub webhooks?**
Yes. Kapture accepts any HTTP method and captures the full request — headers, body, query params, and IP. Drop the endpoint URL into any webhook provider's dashboard.
**Can I run it in production?**
Kapture is designed for local development and testing. For production use, add HTTPS and a stronger password.
**Does it persist logs between restarts?**
Yes. Logs are written to `logs/` as JSONL files (or a single `kapture.db` SQLite file when using `STORAGE_DRIVER=sqlite`). The admin UI lets you browse any daily archive from the sidebar.
**How is this different from webhook.site?**
webhook.site is convenient for one-off testing, but your webhooks go through their servers, expire quickly, and you can't browse yesterday's data. Kapture is self-hosted, open-source, and keeps your logs as long as you configure it to. Your data never leaves your machine. It's not a temporary buffer — it's your webhook archive.
**What if I need to check a webhook from last week?**
Open `/admin?file=2026-05-20` and scroll. Kapture persists logs across restarts, organized by day, browsable from the sidebar. Set `ROTATE_DAYS=90` and you have a 3-month audit trail.
## Roadmap
- [ ] Docker image for one-command deploy
- [ ] Webhook forwarding / replay
- [ ] Configurable log retention per route
- [ ] CLI tail command for live log streaming
## Contributing
Contributions are welcome! Here's how to help:
- [Report a bug](https://github.com/clsmedia/kapture/issues)
- [Submit a pull request](https://github.com/clsmedia/kapture/pulls)
- Star the repo to show support ⭐
## License
MIT