Link Search Menu Expand Document

Bypassing Cloudflare challenges for sites you control

Diagnose screenshots that capture a Cloudflare challenge instead of your page, then create a safe exception for authorized renders.


Only for sites you control

Use this approach only for a domain and Cloudflare account you own or administer. It is not a way to bypass another site’s access controls.

The problem

HCTI loads your page in Chrome from AWS. Cloudflare may classify the request as automated traffic and return a challenge instead of your page. HCTI renders that response, so the image may show Just a moment, appear blank, or time out even though the URL works in your browser.

Because Cloudflare is intentionally withholding the page, increasing ms_delay or retrying the render will not resolve the problem.

This guide is for sites whose Cloudflare configuration you control. It creates a narrow exception for authorized HCTI renders while leaving protections in place for other traffic.

The approach

Send a private value with the HCTI headers parameter, then create a Cloudflare rule that recognizes it and skips only the protection blocking the authorized render.

Do not use identify_as_hcti as the allow signal. Its X-HCTI-SCREENSHOT: 1 value is public and can be copied by anyone.

1. Create a private header

Choose a header name and a long, random value. Treat the value like a password. For example:

Header name:  X-HCTI-Allow
Header value: replace-with-a-long-random-value

Use a value dedicated to this rule so it can be rotated or revoked without affecting another system. A short-lived or regularly rotated value is preferable.

2. Add a Cloudflare skip rule

In the Cloudflare dashboard:

  1. Select your domain and open Security > WAF > Custom rules.
  2. Create a custom rule and place it before the rule or protection issuing the challenge.
  3. Match both your hostname and the private header value:

    (http.host eq "example.com" and any(http.request.headers["x-hcti-allow"][*] eq "replace-with-a-long-random-value"))
    
  4. Choose the Skip action.
  5. Select only the Cloudflare components responsible for the challenge, then deploy the rule.

Cloudflare normalizes header names to lowercase in rule expressions. Its header-field reference documents the request-header map and any() syntax.

Keep the bypass narrow: require the exact hostname and secret value, and skip as few security features as possible. Cloudflare documents the available Skip rule options and explains how rule order affects a Skip custom rule.

3. Send the header with HCTI

Send a standard authenticated JSON request so the private value is not placed in a URL:

curl -X POST https://hcti.io/v1/image \
  -u 'UserID:APIKey' \
  -H 'Content-Type: application/json' \
  -d '{
        "url": "https://example.com/private-report",
        "headers": {
          "X-HCTI-Allow": "replace-with-a-long-random-value"
        }
      }'

The custom header is sent to the top-level document by default. It is restricted to the requested URL’s origin, so a cross-origin redirect will not receive it unless that exact origin is explicitly allowed with additional_header_origins.

4. Verify and troubleshoot

First confirm that an HCTI request without the private header is still challenged and that the request with the correct value succeeds. Then check Cloudflare’s Security Events to identify the product or rule taking action if the request is still blocked.

Cloudflare Skip rules can bypass selected products and phases, including Managed Rules, rate limiting rules, and Super Bot Fight Mode when the corresponding options are available. Cloudflare’s feature-interoperability reference notes that Bot Fight Mode itself cannot be skipped with a custom rule.

If a same-origin CSS file, image, JavaScript file, or API request is challenged separately, set include_headers_on_subrequests to true:

{
  "url": "https://example.com/private-report",
  "headers": {
    "X-HCTI-Allow": "replace-with-a-long-random-value"
  },
  "include_headers_on_subrequests": true
}

If the protected resource uses a different origin, add that exact origin to additional_header_origins:

{
  "url": "https://example.com/private-report",
  "headers": {
    "X-HCTI-Allow": "replace-with-a-long-random-value"
  },
  "additional_header_origins": [
    "https://assets.example.com"
  ],
  "include_headers_on_subrequests": true
}

Custom headers are never sent to an origin outside the requested URL’s origin and this explicit allowlist. Add only origins you control and that use the same private-header rule.

Operational checklist

  • Store the value in your server’s secret manager or environment configuration.
  • Do not put it in client-side JavaScript, source control, or a create-and-render URL.
  • Scope the Cloudflare expression to the expected hostname and exact header value.
  • Keep additional_header_origins limited to exact origins you control.
  • Skip only the feature that blocks the authorized render.
  • Rotate the value periodically and immediately after suspected exposure.

Not a Cloudflare challenge?

If the site is not protected by Cloudflare, or the problem is related to the render’s source IP, network access, or region, an HTTP proxy may be a better fit. Proxies can provide a stable allowlisted IP, access to private content, or different outbound routing.


Need help?

We’re always looking to improve this documentation. Please send us an email: support@htmlcsstoimage.com. We respond fast.


Back to top

Built with extensive integration tests and serious care for developer happiness.
© 2018-2026 Code Happy, LLC.

Page last modified: Jul 31 2026 at 01:29 PM.

Edit this page on GitHub.