451 Unavailable For Legal Reasons
Client error response defined by RFC 7725 §3.
Last updated July 27, 2026
Common causes at a glance
- A court-ordered takedown of specific content
- Geo-blocking to comply with sanctions or a national regulation
- A copyright or right-to-be-forgotten demand acted on by the host
- An upstream ISP or national filter inserting the response in transit
Reproduce it
curl -sSi https://www.example.com/blocked-article | grep -i -E 'HTTP/|^link:'What 451 Unavailable For Legal Reasons means
451 exists to make censorship visible. Before it, a blocked resource was indistinguishable from a deleted one — operators returned 404 or 403 and the reader could not tell whether the page had been removed by its author or suppressed by a third party. 451 says the content exists and someone with legal authority is preventing you from reading it.
The code implies nothing about who imposed the demand. It might be the origin complying with a court order, or an intermediary — an ISP, a national filter, a CDN applying a regional restriction — inserting the response on the operator’s behalf. Distinguishing the two is the point of the accompanying header.
What the spec says
RFC 7725 §3 defines 451 and requires the response body to
explain the legal demand and identify who is behind it. §4 defines the
machine-readable half: a Link header with rel="blocked-by",
built on RFC 8288, naming the entity that imposed the block — not
necessarily the operator returning the response. The spec is candid about its limits:
§5 notes that an operator under a gag order may be forbidden from
sending 451 at all. It is a code for operators permitted to be honest.
What actually causes it
Region-based compliance blocking is the most common source. Sanctions
regimes push operators to refuse whole countries, and rather than serve a bare 403 some
deploy 451 with an explanation. Right-to-be-forgotten requests under GDPR produce per-URL
blocks visible only to European clients. Copyright takedowns work the same way, sometimes
applied by the CDN rather than the origin. The confounding case is a network-level block:
if the response is inserted by an ISP or a national filter, the origin operator may have
no idea it is happening. That is what the blocked-by link is for, and its
absence means the operator either did not implement the header or is not free to name the
demanding party.
How to debug it
Read the headers and the body, then test from somewhere else:
curl -sSi https://www.example.com/blocked-article | grep -i -E '^(HTTP/|link:|server:)'
A Link: <https://legal.example.org/order/9>; rel="blocked-by" names the
responsible entity, and the body is supposed to say more. Then establish whether the block
is geographic by repeating the request from another region: a 200 from one location with a
451 from another confirms geo-blocking. Compare the TLS certificate and
Server header between the two, since a mismatch means something in the path
is intercepting rather than the origin responding. If your own service emits 451, include
the body and the link — a 451 with no explanation is just a 403 with extra mystique.
Working examples
curl
# The Link header and the body carry everything useful.
curl -sSi https://www.example.com/blocked-article \
| grep -i -E '^(HTTP/|link:|content-type:|server:)'
# Is it geographic? Compare from another exit point.
curl -sS -o /dev/null -w '%{http_code}\n' --interface eth1 \
https://www.example.com/blocked-article
Python (requests)
import requests
resp = requests.get("https://www.example.com/blocked-article", timeout=10)
if resp.status_code == 451:
# RFC 7725 section 4: rel="blocked-by" names who imposed the demand.
link = resp.headers.get("Link", "")
print("blocked by:", link if "blocked-by" in link else "not disclosed")
print(resp.text[:500]) # the body must explain the legal demand
Node (fetch)
const res = await fetch("https://www.example.com/blocked-article");
if (res.status === 451) {
const link = res.headers.get("link") ?? "";
const blockedBy = link.includes('rel="blocked-by"') ? link : null;
console.log("blocked by:", blockedBy ?? "undisclosed");
console.log(await res.text());
}
// Retrying will not help; 451 is a policy decision, not a transient failure.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 4xx codes
- 400 Bad Request
- 401 Unauthorized
- 402 Payment Required
- 403 Forbidden
- 404 Not Found
- 405 Method Not Allowed
- 406 Not Acceptable
- 407 Proxy Authentication Required
- 408 Request Timeout
- 409 Conflict
- 410 Gone
- 411 Length Required
- 412 Precondition Failed
- 413 Content Too Large
- 414 URI Too Long
- 415 Unsupported Media Type
- 416 Range Not Satisfiable
- 417 Expectation Failed
- 418 (Unused)
- 419 Page Expired
- 421 Misdirected Request
- 422 Unprocessable Content
- 423 Locked
- 424 Failed Dependency
- 425 Too Early
- 426 Upgrade Required
- 428 Precondition Required
- 429 Too Many Requests
- 431 Request Header Fields Too Large
- 444 No Response
- 494 Request Header Too Large
- 495 SSL Certificate Error
- 496 SSL Certificate Required
- 497 HTTP Request Sent to HTTPS Port
- 499 Client Closed Request