API — Ports & traffic

Open, close, list and configure proxy ports, and test an upstream before you commit to it. These are the endpoints you'll use most when integrating BlankTrail Proxy.

Open a port

POST /api/v1/ports/open Auth required

Opens a new proxy port with the given configuration and returns the identity it will present.

ParameterTypeRequiredDescription
portintYesThe local TCP port to open.
protocolstringNo"socks5" or "http" (default "http").
modestringNoHow the identity is selected: "random", "db", "auto" or "specific".
browserstringNoBrowser filter, e.g. "chrome", "firefox", "safari", "edge" (optionally with a version).
osstringNoOS filter: "windows", "macos", "linux" or "ios".
upstreamstringNoUpstream proxy, e.g. "socks5://user:pass@host:1080". Empty for direct.
upstream_gatewaystringNoName of a saved gateway to route through instead of a raw upstream.
spoof_headersboolNoWhether to normalize outgoing HTTP headers to match the identity.
timeout_secondsintNoIdle timeout on an established connection, in seconds. The connection is dropped after this long with no bytes travelling in either direction. Default 60. Raise it for WebSocket, SSE or long-poll traffic, which stays quiet by design. While a challenge is being solved the wait is extended for the duration of the solve.
connect_timeout_secondsintNoCap on a SINGLE connect attempt to the egress, in seconds. Default 5. A reachable egress answers within tens of milliseconds even across an ocean, so a lower value drops dead proxies faster, while a higher one only helps deliberately slow egresses.
request_timeout_secondsintNoSilence budget, in seconds. Default 30; 0 removes the limit. It covers the whole connect phase including retries, and then the wait for the first byte of the response. The first byte clears it and the rest of the transfer is governed by timeout_seconds, so a large or slow download is never cut short. On keep-alive every subsequent request gets a fresh budget.
chain_proxystringNoFirst-hop proxy placed before the upstream, in the same format as upstream. Lets you compose a multi-hop route.
chain_gatewaystringNoSaved gateway used as the first hop instead of chain_proxy.
specific_profilestringNoProfile name to pin, for mode "specific".
idle_secondsintNoPort lifetime, in seconds: the port itself is closed after this long without traffic. Omit it to inherit the global setting; 0 keeps the port open indefinitely. Distinct from timeout_seconds, which governs a single connection.
decompressboolNoDecode a br/gzip/zstd response body to plain bytes for your client.
max_concurrentintNoCap on connections this port handles at once. 0 means no cap.
skip_retryboolNoDo not retry an upstream that refused the connection; return the error immediately instead.
retry_delay_msintNoPause before a connection retry, in milliseconds.
leak_guardstringNoPre-start DNS/IPv6 leak check on the egress: "off", "warn" or "enforce". With "enforce" a leaking egress refuses to open the port.
upstream_tls_insecureboolNoSkip certificate verification for an https:// upstream. Use it only for your own proxy with a self-signed certificate: the proxy login, its password and every CONNECT target travel over that connection.
enable_http3boolNoRe-originate over HTTP/3 when the target offers it and the egress can carry UDP.
js_solverboolNoChallenge Breaker: route challenged requests through the solver pool. Requires a port that inspects traffic (not tls_passthrough).
keep_sessionsboolNoGive the port its own per-domain cookie jar, so a session survives across requests.
Request body
{
  "port": 20134,
  "protocol": "socks5",
  "mode": "random",
  "browser": "chrome",
  "os": "windows"
}
Example (curl)
curl -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"port":20134,"protocol":"socks5","mode":"random","browser":"chrome"}' \
  http://127.0.0.1:8891/api/v1/ports/open
Response
{
  "port": 20134,
  "protocol": "socks5",
  "status": "opened",
  "current_profile": {
    "name": "Chrome_145_Windows_10",
    "browser": "chrome",
    "os": "windows",
    "user_agent": "Mozilla/5.0 ..."
  }
}

Close a port

POST /api/v1/ports/close Auth required

Closes an open port and frees it.

ParameterTypeRequiredDescription
portintYesThe port to close.
Request body
{ "port": 20134 }
Example (curl)
curl -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"port":20134}' http://127.0.0.1:8891/api/v1/ports/close

List open ports

GET /api/v1/ports Auth required

Returns every open port with its status, plus your total and maximum port counts.

Example (curl)
curl -H "X-API-Key: YOUR_API_KEY" http://127.0.0.1:8891/api/v1/ports
Response
{
  "ports": [
    { "port": 20134, "protocol": "socks5", "status": "open" }
  ],
  "total_open": 1,
  "max_ports": 10000
}

Suggest a free port

GET /api/v1/ports/suggest Auth required

Returns an available port number you can open.

Example (curl)
curl -H "X-API-Key: YOUR_API_KEY" http://127.0.0.1:8891/api/v1/ports/suggest
Response
{ "port": 20123 }

Test an upstream

POST /api/v1/upstream/test Auth required

Pre-flight checks an upstream chain: reachability, SOCKS5 UDP support, and DNS/IPv6 leaks — before you open a port.

ParameterTypeRequiredDescription
checksstring[]YesAny of "http", "udp", "leak".
protocolstringNo"socks5" or "http".
upstreamstringNoThe upstream proxy to test (empty for direct).
chain_proxystringNoAn optional first hop before the upstream.
Request body
{
  "checks": ["http", "leak"],
  "protocol": "socks5",
  "upstream": "socks5://user:pass@host:1080"
}
Response
{
  "http": { "ok": true, "detail": "200 in 45ms" },
  "leak": { "ok": true, "detail": "no DNS/IPv6 leak — exit 203.0.113.45" }
}

Get a port's configuration

GET /api/v1/port/{port}/status Auth required

Returns the full configuration snapshot for one port.

Example (curl)
curl -H "X-API-Key: YOUR_API_KEY" http://127.0.0.1:8891/api/v1/port/20134/status
GET /api/v1/port/{port}/config Auth required

Returns the port configuration in exactly the shape PUT accepts, so you can read it, change one field and send it back.

PUT /api/v1/port/{port}/config Auth required

Edits a live port in place: the listener is not dropped, existing connections survive and the identity is preserved unless mode or the filters change. The body is partial — only the fields you send are changed, everything else keeps its current value. Sending an explicit empty value still clears a field, so removing an upstream stays expressible. The protocol cannot be changed on a live port.

ParameterTypeRequiredDescription
protocolstringNoOnly accepted if it matches the port protocol; a mismatch is rejected. Close and reopen the port to change it.
...anyNoAny field of POST /api/v1/ports/open other than port and protocol.

Change per-port settings

Each port setting has a matching GET/PUT endpoint under /api/v1/port/{port}/…. Send the value in the body. For example, set the upstream or toggle header spoofing:

PUT /api/v1/port/{port}/upstream Auth required

Sets the upstream proxy for a port.

Request body
{ "upstream": "socks5://user:pass@host:1080" }
Example (curl)
curl -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" -X PUT \
  -d '{"upstream":"socks5://user:pass@host:1080"}' \
  http://127.0.0.1:8891/api/v1/port/20134/upstream

Other per-port settings follow the same pattern, including: mode, browser, os, chain_proxy, spoof_user_agent, spoof_headers, h2_spoofing and idle.

GET /api/v1/port/{port}/decompress Auth required

Reports whether compressed response bodies are decoded for the client.

PUT /api/v1/port/{port}/decompress Auth required

Turns body decoding on or off.

ParameterTypeRequiredDescription
enabledboolYestrue decodes br/gzip/zstd bodies to plain bytes.
GET /api/v1/port/{port}/captures Auth required

Returns the fingerprints captured by a debug capture port. Only available on a port opened with debug_capture.

ParameterTypeRequiredDescription
sinceintNoReturn only captures newer than this sequence number.
limitintNoMaximum number of captures to return.
DELETE /api/v1/port/{port}/captures Auth required

Clears the capture ring of a debug capture port.