proxycanary

docs

How proxycanary reads, probes and reports.

Everything the checker does, in the order it does it. If something here disagrees with what you see on the site, the site is the bug.

Proxy formats

One proxy per line, or separated by commas or spaces. Junk lines are skipped and counted; duplicates are collapsed.

203.0.113.10:8080
user:[email protected]:8080
203.0.113.10:8080:user:pass
socks5://203.0.113.10:1080
http://user:[email protected]:3128

A scheme (http, https, socks4, socks5) pins the protocol. Without one, the protocol is detected. Credentials are used for the probe and echoed back to you in the results.

Protocols and detection

http
Plain HTTP proxy. The judge request is sent with an absolute URL.
https
HTTP proxy that accepts CONNECT. We tunnel a TLS session to the judge's port 443.
socks4
SOCKS4 CONNECT to the judge, then a plain HTTP request inside the tunnel.
socks5
SOCKS5 CONNECT, with username/password auth when credentials are given.

With no scheme and protocol set to Auto, the order is http, then socks5, then socks4. The first protocol that yields a valid judge response wins. A refused connection or a connect timeout stops the sequence early, since another handshake will not change that.

Anonymity levels

The judge is a plain-HTTP endpoint that returns the address it saw the request come from and every header it received. The level is decided from that, not from anything the proxy claims about itself.

transparent
Your real address appeared in a forwarded header (X-Forwarded-For, Forwarded, X-Real-IP, Via and friends).
anonymous
Your address was hidden, but a header gave the proxy away (Via, X-Forwarded-For with another address, Proxy-Connection, X-Cache, ...).
elite
Neither. The judge saw an ordinary request from the exit address.

CONNECT tunnels (the https protocol) carry no proxy headers by design, so their anonymity is judged from the plain-HTTP attempt when one succeeded.

Network kinds

The exit address is looked up in an IP intelligence database. Three flags come back and are shown as one label:

mobile
The exit belongs to a carrier range, the kind phones get their addresses from.
dc
A hosting or cloud provider range. These are the first to be blocked by anti-bot systems.
isp
Anything else: a consumer or business ISP line, usually called residential.

Country, city, ISP and ASN come from the same lookup. Lookups are cached for 30 days, so a range that changes hands may lag by up to that long.

Limits

per run
10,000 proxies. Longer lists are cut at 10,000.
concurrency
200 probes at a time, shared across all runs on the service.
timeout
1 to 10 seconds per proxy, default 5. Covers connect plus the full request.
bulk runs
30 per 10 minutes per address.
single checks
60 per minute per address.

API

The same checker the site uses. No key. Send JSON, read server-sent events. Cancel a run by closing the connection.

POST /api/check

curl -N -X POST https://proxycanary.com/api/check \
  -H "Content-Type: application/json" \
  -d '{
    "proxies": ["203.0.113.10:8080", "socks5://198.51.100.7:1080"],
    "protocol": "http",        // optional: http | https | socks4 | socks5
    "timeoutMs": 5000          // optional: 1000..10000
  }'

Events, in order: one start, one result per proxy (alive rows may arrive twice, the second time with geo), one done.

event: start
data: {"type":"start","runId":"…","total":2,"skipped":0}

event: result
data: {"type":"result","result":{"id":"0","proxy":{"host":"203.0.113.10","port":8080},
  "status":"alive","protocol":"http","latencyMs":112,"connectMs":38,
  "anonymity":"elite","exitIp":"203.0.113.10","countryCode":"DE",
  "country":"Germany","asn":"AS24940","mobile":false,"hosting":true}}

event: result
data: {"type":"result","result":{"id":"1","proxy":{"host":"198.51.100.7","port":1080},
  "status":"dead","error":"connect_timeout"}}

event: done
data: {"type":"done","runId":"…","alive":1,"dead":1,"durationMs":5210}

POST /api/check/single

curl -X POST https://proxycanary.com/api/check/single \
  -H "Content-Type: application/json" \
  -d '{"proxy": "203.0.113.10:8080"}'

Returns one JSON object with the fields above plus judgeHeaders (what the judge received), intel (the full network lookup) and triedProtocols. The id is the report id used by GET /api/report/:id and the share link at /r/:id.

Errors

connect_timeout
No TCP connection within the timeout.
connection_refused
Port closed or firewalled.
read_timeout
Connected, but no complete response in time.
auth_required
The proxy wants credentials (407 or SOCKS auth failure).
judge_status_NNN
The proxy answered with an HTTP status instead of relaying (403, 503, ...).
bad_judge_response
Something answered, but not the judge. Usually a captive page or a block page.
tampered_response
A judge-shaped response that did not carry our request. Treated as dead.
not_socks
The declared SOCKS version was not spoken on that port.