How to Mock a Webhook Subscribe Callback URL in Python

Mock a webhook subscribe callback URL using Python's http.server to receive and parse POST requests sent by webhook providers.

Medium Python 3.9+ Aug 9, 2026 API design & gRPC 15 views 0 copies

Python code

25 lines
Python 3.9+
import json
from http.server import BaseHTTPRequestHandler, HTTPServer

class WebhookHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        content_length = int(self.headers.get('Content-Length', 0))
        payload = json.loads(self.rfile.read(content_length)) if content_length else {}
        
        print(f"Webhook received: {payload}")
        self.send_response(200)
        self.send_header('Content-Type', 'application/json')
        self.end_headers()
        self.wfile.write(json.dumps({"status": "ok"}).encode())

    def log_message(self, format, *args):
        pass

def start_mock_webhook_server(port=8080):
    server = HTTPServer(('localhost', port), WebhookHandler)
    print(f"Mock webhook server listening on port {port}")
    server.handle_request()
    server.server_close()

if __name__ == "__main__":
    start_mock_webhook_server()

Output

stdout
Mock webhook server listening on port 8080
Webhook received: {'event': 'sale', 'store_id': 42, 'product': 'velcro shoes'}

How it works

This code subclasses BaseHTTPRequestHandler to handle POST requests, reading the Content-Length header to determine how much data to read from the request body. It parses the JSON payload with json.loads and prints it for visibility. The response is a simple 200 OK with a JSON body, which is what most webhook providers expect as an acknowledgment. The log_message override suppresses default logging to keep output clean. The server uses handle_request() to process a single request before closing — useful for testing one callback in isolation.

Common mistakes

  • Forgetting to call `send_response` before writing the response body
  • Not setting `Content-Type` header before `end_headers()`
  • Assuming the request body is JSON without handling empty payloads
  • Calling `handle_request()` in a loop without proper cleanup

Variations

  1. Use a while loop with `serve_forever()` to handle multiple callback requests sequentially
  2. Use `http.server.ThreadingHTTPServer` to handle concurrent webhook deliveries

Real-world use cases

  • Testing a Stripe or PayPal webhook subscription by pointing the callback URL at your local mock server during development.
  • Verifying that your event-processing pipeline sends correct POST bodies to a registered webhook URL.
  • Simulating third-party API callbacks in integration tests without relying on external services.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from API design & gRPC

Related tutorials and quizzes for this topic.