Agent API
The running agent serves an API next to its web inspector, at http://127.0.0.1:4040/api (4041 and up when
several agents run). Its calls and JSON follow ngrok’s agent API, so the usual one-liner for grabbing the public URL keeps working:
$ curl -s localhost:4040/api/tunnels | jq -r '.tunnels[0].public_url' Calls
| Call | What it does |
|---|---|
GET /api/tunnels | Running tunnels: name, public_url, config.addr, connection counts. |
GET /api/tunnels/:name | One tunnel. |
POST /api/tunnels | Start a tunnel: name, addr, url (or domain), traffic_policy, pooling_enabled, host_header. |
DELETE /api/tunnels/:name | Stop it. |
GET /api/requests/http | Captured requests, newest first; ?limit=, ?tunnel_name=. Bodies come base64 in raw. |
GET /api/requests/http/:id | One request and its response. |
POST /api/requests/http | Replay a request: {"id": "12"}. |
DELETE /api/requests/http | Clear the captured requests. |
Starting a tunnel from a script
shell curl -s localhost:4040/api/tunnels \
-H 'Content-Type: application/json' \
-d '{"name": "api", "addr": "9000", "url": "https://api.example.internal"}'
It answers with the tunnel, its public_url included, once the session is up.
Questions people actually ask
Yes for the common calls: /api/tunnels to read the public URL, starting and stopping tunnels, and /api/requests/http to list, read and replay captured requests answer in ngrok’s JSON shapes on the same port, 4040.
No. It answers only on localhost, refuses other Host headers (DNS rebinding), and accepts changes only as JSON or DELETE requests, which a cross-site page can’t send without a CORS preflight the agent never grants.