Skip to content

Error responses

When Cloudflare cannot complete a request, it generates an error response. The format depends on what the client requests via the Accept header and on the zone's Custom Errors configuration.

By default, error responses are HTML. Clients that request a structured format (such as application/json, application/problem+json, or text/markdown) receive a machine-readable response instead. This machine-readable response covers all 1xxx error codes (which return HTTP 4xx or 5xx status codes depending on the error) and Cloudflare-generated 5xx errors (500, 502, 504, 520-526). Responses for 5xx errors generated by the origin server are passed through by Cloudflare to the client and are not affected.


Content negotiation

Cloudflare selects the response format based on the client's Accept header, following standard HTTP content negotiation. When multiple formats are acceptable, quality factors (q values) determine precedence. At the same quality value, the first-listed type wins.

Accept header sentResponse format
application/jsonJSON (application/json; charset=utf-8)
application/problem+jsonJSON (application/problem+json; charset=utf-8)
application/json, text/markdown;q=0.9JSON (higher quality factor)
text/markdownMarkdown (text/markdown; charset=utf-8)
text/markdown, application/jsonMarkdown (equal quality, first-listed wins)
text/*Markdown
text/htmlHTML
*/*HTML
Not setHTML

Structured error responses are available on all plans, including the Free plan. Custom Error Rules for overriding these responses require a Cloudflare paid plan.


Interaction with Custom Errors

Structured error responses are the default for zones with no custom error configuration. Zones that use Custom Errors retain full control over what clients receive.

What a client receives depends on which custom error features your zone has configured. Refer to the following sections for details.

No custom error page, no custom error rules

This is the default for most zones. Cloudflare serves its default error response in the format the client requests.

Client sendsResponse
Accept: application/jsonDefault Cloudflare structured JSON response
Accept: text/markdownDefault Cloudflare structured Markdown response
Accept: text/htmlDefault Cloudflare HTML error page
No Accept headerDefault Cloudflare HTML error page

Error Page configured, no custom error rules

The zone has an Error Page uploaded via the Cloudflare dashboard. No Custom Error Rules are configured. The Error Page is served to all clients regardless of Accept header — Error Pages do not perform content negotiation.

Client sendsResponse
Accept: application/jsonYour custom HTML error page
Accept: text/markdownYour custom HTML error page
Accept: text/htmlYour custom HTML error page
No Accept headerYour custom HTML error page

If you want agents to receive structured responses while keeping your custom HTML for browsers, add a Custom Error Rule that matches on the Accept header. Refer to the next section for details.

Custom Error Rules configured

The zone has one or more Custom Error Rules (available on paid plans). These take priority over Error Pages. You control what gets served, to whom, and under what conditions.

Client sendsResponse
Accept: application/jsonIf a Custom Error Rule matches, the rule's content is served. If no rule matches, falls back to the Error Page (if configured) or the structured JSON response.
Accept: text/markdownIf a Custom Error Rule matches, the rule's content is served. If no rule matches, falls back to the Error Page (if configured) or the structured Markdown response.
Accept: text/htmlIf a Custom Error Rule matches, the rule's content is served. If no rule matches, falls back to the Error Page or the default HTML.
No Accept headerSame fallback chain

Custom Error Rules can match on any request header including Accept, and can target specific error codes. You can serve JSON to API clients, Markdown to agents, and HTML to browsers, all from the same zone.

Example: Serve custom JSON to API clients on a 522 error

This Custom Error Rule matches 522 errors where the client requests JSON:

Expression: (http.response.code eq 522) and (any(http.request.headers["accept"][*] contains "application/json"))

Action: Serve a custom JSON response with your own error format.

This rule takes priority over both the default structured JSON response and any configured Error Page. Clients that do not match the rule (for example, browsers requesting HTML) fall through to the Error Page or the default Cloudflare response.

Example: Serve structured responses to agents and a custom HTML page to browsers

If your zone has an Error Page configured, it is served to all clients, including agents requesting JSON or Markdown. To let agents receive Cloudflare's default structured responses instead, remove the Error Page. Without an Error Page, Cloudflare respects the Accept header automatically: agents get structured JSON or Markdown and browsers get HTML.

If you need to keep the Error Page for browsers but want to serve custom structured content to agents, create Custom Error Rules that match on the Accept header and serve your own JSON or Markdown content. Browsers that do not match either rule continue to receive your custom HTML Error Page.

Priority order

When Cloudflare generates an error response, the following priority order determines what the client receives:

  1. Custom Error Rules — If a rule matches the error and request conditions, the rule's content is served.
  2. Error Pages — If an Error Page is configured for the error type and no Custom Error Rule matched, the Error Page is served as HTML regardless of the Accept header.
  3. Structured error responses — If no Custom Error Rule matched and no Error Page is configured, Cloudflare serves its default response in the format the client requested (JSON, Markdown, or HTML).

For the full priority order including account-level versus zone-level rules, WAF custom block responses, and security challenge pages, refer to the Custom Errors documentation.


Examples

JSON: 522 Connection timed out

{
"type": "https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-522/",
"title": "Error 522: Connection timed out",
"status": 522,
"detail": "Cloudflare could not establish a TCP connection to the origin server. The TCP handshake timed out, which may indicate the origin is overloaded, firewalling Cloudflare, or unreachable at the network level.",
"instance": "9f140b785e57c458",
"error_code": 522,
"error_name": "connection_timeout",
"error_category": "origin",
"ray_id": "9f140b785e57c458",
"timestamp": "2026-04-24T09:22:40Z",
"zone": "example.com",
"cloudflare_error": true,
"retryable": true,
"retry_after": 120,
"owner_action_required": true,
"what_you_should_do": "**Wait and retry.** Back off for at least 120 seconds. If the error persists, the website operator should verify firewall rules and ensure the origin accepts connections from Cloudflare IP ranges.",
"footer": "This error was generated by Cloudflare on behalf of the website owner."
}

Markdown: 522 Connection timed out

---
error_code: 522
error_name: connection_timeout
error_category: origin
status: 522
ray_id: 9f140b785e57c458
timestamp: 2026-04-24T09:22:40Z
zone: example.com
cloudflare_error: true
retryable: true
retry_after: 120
owner_action_required: true
---
# Error 522: Connection timed out
## What Happened
Cloudflare could not establish a TCP connection to the origin server. The TCP handshake timed out, which may indicate the origin is overloaded, firewalling Cloudflare, or unreachable at the network level.
## What You Should Do
**Wait and retry.** Back off for at least 120 seconds. If the error persists, the website operator should verify firewall rules and ensure the origin accepts connections from Cloudflare IP ranges.
---
This error was generated by Cloudflare on behalf of the website owner.

Test structured error responses

Fetch the structured JSON response for a 522 error:

Terminal window
curl --silent --compressed --header "Accept: application/json" \
--user-agent "TestAgent/1.0" --header "Accept-Encoding: gzip, deflate" \
"https://example.com/cdn-cgi/error/522" | jq .

Fetch the structured Markdown response:

Terminal window
curl --silent --compressed --header "Accept: text/markdown" \
--user-agent "TestAgent/1.0" --header "Accept-Encoding: gzip, deflate" \
"https://example.com/cdn-cgi/error/522"

Check for the Retry-After header on a retryable error:

Terminal window
curl --silent --compressed --dump-header - --output /dev/null \
--header "Accept: application/json" --user-agent "TestAgent/1.0" \
--header "Accept-Encoding: gzip, deflate" \
"https://example.com/cdn-cgi/error/521" | grep -i retry-after

Response fields

Both JSON and Markdown responses contain the same set of fields. JSON responses return them as a flat object; Markdown responses place them in YAML frontmatter followed by prose sections. The field definitions below apply to both formats.

JSON responses follow RFC 9457 (Problem Details for HTTP APIs). Any HTTP client that understands Problem Details can parse the five standard members (type, title, status, detail, instance) without Cloudflare-specific code.

RFC 9457 standard members

FieldTypeDescription
typestringURI pointing to Cloudflare documentation for this error code.
titlestringShort summary, for example, "Error 522: Connection timed out".
statusintegerHTTP status code of the response.
detailstringPlain-text explanation of what went wrong and which party is responsible.
instancestringRay ID identifying this specific error occurrence.

Cloudflare extension members

FieldTypeDescription
error_codeintegerCloudflare error code (for example, 522, 1015).
error_namestringMachine-readable name in snake_case (for example, connection_timeout, rate_limited). Stable — suitable for programmatic matching.
error_categorystringFault classification. Refer to Error categories. Stable — suitable for programmatic matching.
ray_idstringSame value as instance. Included for compatibility with existing Cloudflare tooling.
timestampstringISO 8601 timestamp of when the error was generated.
zonestringThe requested hostname.
cloudflare_errorbooleanAlways true. Confirms this error was generated by Cloudflare, not the origin.
retryablebooleanWhether the error is transient and the request can be retried.
retry_afterinteger or nullSeconds to wait before retrying. Present only when retryable is true. Matches the Retry-After HTTP header value.
owner_action_requiredbooleanWhether the site operator needs to take action to resolve the error.
what_you_should_dostringActionable guidance for the client: what to do next, whether to retry, and who can fix the problem.
footerstringAttribution line.

Markdown-specific structure

Markdown responses place these fields in YAML frontmatter (between --- delimiters), followed by three prose sections:

  • # Error {code}: {description} — heading with the error code and short description.
  • ## What Happened — corresponds to the detail field.
  • ## What You Should Do — corresponds to the what_you_should_do field.

The frontmatter omits the RFC 9457 standard members (type, title, instance) and the footer field since these are either redundant with the prose or not applicable to the Markdown format.


Error categories

The error_category field classifies the fault so that clients can route retry and escalation behavior without parsing the prose fields.

5xx error categories

CategoryCodesMeaningRetry?
origin502, 504, 520-524The origin server is responsible. Transient infrastructure failure.Yes. Back off using retry_after.
cloudflare500Cloudflare encountered an internal error. The origin was not necessarily involved.Yes. Short retry (30s).
ssl525, 526The origin's TLS configuration is broken (handshake failure or invalid certificate).No. Retrying will not help until the operator fixes the TLS configuration.

1xxx error categories

CategoryMeaningExample codes
access_deniedIP blocks, country blocks, firewall rules1005, 1006, 1007, 1008, 1010, 1012, 1106-1109
rate_limitRate limiting1015, 1025, 1027, 1200
dnsDNS resolution errors1001, 1016
configZone or origin configuration errors1004, 1014, 1033, 1043, 1047, 1049
tlsClient TLS errors (version, cipher, certificate)1017, 1028, 1029, 1044
legalLegal restrictions (DMCA, country blocks)1026, 1039
workerWorker script errors1042, 1100, 1101, 1102, 1103, 1104, 1105
rewriteURL rewrite rule errors1036, 1037
snippetSnippet configuration errors1201, 1202, 1203, 1204, 1205, 1206
unsupportedUnsupported features or protocols1045

Retry-After header

Retryable error codes include a standard Retry-After HTTP response header. The header value in seconds matches the retry_after field in the response body.

5xx Retry-After values

Coderetry_after (in seconds)
50030
50260
504120
52060
521120
522120
523120
524120
525N/A (not retryable)
526N/A (not retryable)

Non-retryable codes (525, 526) do not include the Retry-After header.

1xxx Retry-After values

Six retryable 1xxx error codes emit Retry-After:

Coderetry_after (in seconds)Error name
1004120DNS resolution error
101530Rate limited
1033120Argo Tunnel error
103860HTTP headers limit exceeded
120060Cache connection limit
12055Too many redirects

All other 1xxx error codes are non-retryable and do not include the Retry-After header.

If a WAF rate limiting rule has already set a dynamic Retry-After value on the response, that value takes precedence over the default.


More resources