511 Network Authentication Required
Server error response defined by RFC 6585 §6.
Last updated July 27, 2026
Common causes at a glance
- A captive portal on hotel, airport, or conference Wi-Fi intercepting the request
- A corporate network requiring sign-in before allowing outbound traffic
- An ISP interception page for an unpaid or suspended account
- An origin server misusing 511 where 401 or 403 is correct
Reproduce it
curl -i --max-time 5 http://captive.apple.com/hotspot-detect.htmlWhat 511 Network Authentication Required means
A captive portal intercepts traffic from unauthenticated clients and answers with its own content, so a request to one host returns a response written by something else entirely. That breaks non-browser agents badly: a package manager or a monitoring script sees a 200 carrying a login page and caches or parses it as though it came from the real server.
511 fixes the reporting, not the interception. A portal that answers 511 tells the client unambiguously that the response came from the network rather than the origin, so a well-behaved agent can stop, avoid caching, and surface something useful instead of a parse error. The detection endpoints Apple and Android devices probe on boot exist precisely because so few portals ever implemented 511 correctly.
What the spec says
RFC 6585 §6 defines 511 and is unusually prescriptive. The response representation SHOULD contain a link to a resource where credentials can be submitted, but SHOULD NOT contain the login interface itself, because a browser would then show that interface as belonging to the originally requested URL. Responses with 511 MUST NOT be stored by a cache, and the code SHOULD NOT be generated by origin servers — it is for intercepting proxies only. §6.1 states plainly that it is not intended to encourage such deployments, only to limit their damage. The successor for signalling portal state is the Captive Portal API in RFC 8908.
What actually causes it
511 feels rare despite captive portals being everywhere because interception only works over cleartext HTTP. A portal cannot intercept an HTTPS request and return a 511: it has no certificate for the origin’s hostname, so the handshake fails and the client sees a certificate error or a connection reset rather than any status code. Portals that try to redirect HTTPS produce exactly the confusing failures 511 was meant to eliminate. That is why operating systems probe a hard-coded cleartext URL to detect captivity, and why a script that only speaks HTTPS fails obscurely on a captive network.
How to debug it
Probe over plain HTTP, because that is the only path a portal can intercept:
curl -sS -D - --max-time 5 http://captive.apple.com/hotspot-detect.html | head -20
On an open network that returns 200 with a tiny body containing the word
Success. On a captive network you get a 511, a 302 to the portal, or a 200
carrying the portal’s own HTML. All three mean you are captive; only the first is well
behaved. Then try the same host over HTTPS: a TLS error where the cleartext probe
succeeded confirms interception rather than a routing fault. Portals hijack DNS too, so
compare against a known resolver with the DNS lookup tool.
Working examples
curl
# Cleartext probe: the only request a portal can intercept and answer.
curl -sS -D - --max-time 5 http://captive.apple.com/hotspot-detect.html | head -20
# Same host over TLS. A handshake failure here, plus a portal page above,
# means interception rather than a routing problem.
curl -sS -o /dev/null -w '%{http_code}\n' --max-time 5 \
https://captive.apple.com/hotspot-detect.html
Python (requests)
import requests
probe = requests.get(
"http://captive.apple.com/hotspot-detect.html",
timeout=5,
allow_redirects=False,
)
if probe.status_code == 511:
print("captive portal, correctly signalled")
elif probe.status_code in (301, 302, 307) or "Success" not in probe.text:
print("captive portal, badly signalled:",
probe.status_code, probe.headers.get("Location"))
else:
print("network is open")
Node (fetch)
const probe = await fetch("http://captive.apple.com/hotspot-detect.html", {
redirect: "manual",
signal: AbortSignal.timeout(5000),
});
if (probe.status === 511) {
console.log("captive portal (RFC 6585 compliant)");
} else if (probe.status >= 300 && probe.status < 400) {
console.log("captive portal redirect to", probe.headers.get("location"));
} else if (!(await probe.text()).includes("Success")) {
console.log("response body was rewritten: captive network");
} else {
console.log("network is open");
}Reference and tooling
The authoritative list of assigned status codes is theIANA HTTP Status Code Registry. For a searchable copy with the semantics summarised, use theHTTP status code reference on this site. To see exactly what a server is sending, theheader inspector shows the raw status line and response headers, and thecurl builder assembles the request flags for you.
Other 5xx codes
- 500 Internal Server Error
- 501 Not Implemented
- 502 Bad Gateway
- 503 Service Unavailable
- 504 Gateway Timeout
- 505 HTTP Version Not Supported
- 506 Variant Also Negotiates
- 507 Insufficient Storage
- 508 Loop Detected
- 510 Not Extended
- 520 Web Server Returns an Unknown Error
- 521 Web Server Is Down
- 522 Connection Timed Out
- 523 Origin Is Unreachable
- 524 A Timeout Occurred
- 525 SSL Handshake Failed
- 526 Invalid SSL Certificate
- 530 Unable to Resolve Origin Hostname