Set up webhooks at cloud.browser-use.com/settings?tab=webhooks.
Events
Match the event type to the API version you use. For V4 run monitoring, see Observability and polling guidance.
Payload
A V2 task event includes task_id, session_id, status, and task metadata:
A V3 event uses the session’s id as payload.session_id. output is included when available:
Status-change events are not all completion events. Check the status before continuing your workflow.
Signature verification
Every webhook request includes two headers:
X-Browser-Use-Signature: lowercase hexadecimal HMAC-SHA256 signature.
X-Browser-Use-Timestamp: Unix timestamp in seconds when this delivery was sent.
The signed message is the UTF-8 encoding of {header_timestamp}.{canonical_payload}. The canonical payload is exactly Python’s json.dumps(payload, sort_keys=True, separators=(',', ':'), ensure_ascii=True), applied to the entire event, including its type, timestamp, and payload.
This is not a signature over the raw HTTP body. The sender serializes the HTTP body separately. Non-ASCII characters are escaped in the signed representation: for example, München becomes M\u00fcnchen.
JavaScript JSON.stringify, even after sorting an object’s keys, does not implement this format. Unicode escaping, integer-like object keys, and number formatting can differ from Python. Do not use a generic JavaScript JSON canonicalizer or raw-body HMAC verifier for this contract. The Python verifier below matches the current sender; other implementations must match its serialization exactly and preserve number representations when parsing.
Save this as webhook_verify.py:
The five-minute timestamp window limits replay, but does not make delivery unique. Make your business action idempotent so a duplicate callback cannot process the same result twice. Keep your server clock synchronized.
Example: FastAPI webhook handler
Install fastapi and uvicorn, put this app.py beside webhook_verify.py, set WEBHOOK_SECRET to the signing secret from your webhook settings, and run uvicorn app:app --port 3000.
Return promptly after durably accepting the event. The sender has a 10-second request timeout and retries temporary failures, so slow processing can cause duplicate deliveries. HTTP 400, 401, 403, 404, and 410 are not retried.
For local development, expose your local server with a tool such as ngrok: ngrok http 3000. Set the resulting /webhook URL in the dashboard and use its test action before starting tasks.