---
type: Integration Guide
title: "Cloudflare prerendering integration"
description: "Use Cloudflare Workers to detect crawlers at the edge and route them to a prerendering source — typically the cleanest setup for SPAs and JAMstack sites."
resource: "https://prerendering.com/integrations/cloudflare"
tags: [integration, cloudflare]
timestamp: 2026-05-11T00:00:00Z
---

# Cloudflare prerendering integration

Use Cloudflare Workers to detect crawlers at the edge and route them to a prerendering source — typically the cleanest setup for SPAs and JAMstack sites.

Cloudflare Workers run before the request reaches the origin, making them ideal for bot detection and prerender routing. The pattern works for any origin (Vercel, AWS, self-hosted) — the Worker decides where to send each request based on user-agent and verified-bot signals.

## Best for

- SPAs and JAMstack sites with Cloudflare in front
- Teams that want platform-agnostic prerendering routing
- Sites already using Cloudflare for DDoS, CDN, or DNS

## Setup

Deploy a Worker that intercepts all requests, classifies the user-agent, and rewrites bot requests to a prerender service. Use Cloudflare's Bot Management or IP Lists for reliable verification.

```js
// Full guide: https://github.com/ostr-io/ostrio-docs/blob/master/docs/prerendering/examples/cloudflare-worker/coudflare-worker-guide.md
export default {
  async fetch(request, env) {
    const AUTH_HEADER = env.OSTR_AUTH || BASIC_TOKEN || DICT.service.testAuth;
    const url = new URL(request.url);
    const userAgent = (request.headers.get(DICT.headers.ua) || DICT.stringEmpty).toLowerCase();
    const hasEscapedFragment = url.searchParams.has(DICT.escapedFragment);

    if (!shouldPrerender(request, url, userAgent)) {
      return fetch(request);
    }

    const headers = new Headers(request.headers);
    headers.delete(DICT.headers.auth);
    headers.set(DICT.headers.auth, AUTH_HEADER);

    let fetchUrl = url.origin;
    if (SUPPORT_ESCAPED_FRAGMENT && hasEscapedFragment) {
      const escapedFragment = url.searchParams.get(DICT.escapedFragment);
      url.searchParams.delete(DICT.escapedFragment);

      if (escapedFragment.length) {
        fetchUrl += `${url.pathname.replace(trailingSlashRe, DICT.stringEmpty)}${DICT.slash}${escapedFragment.replace(beginningSlashRe, DICT.stringEmpty)}`;
      } else {
        fetchUrl += url.pathname.replace(trailingSlashRe, DICT.stringEmpty);
      }
    } else {
      fetchUrl += url.pathname;
    }

    if (PRERENDER_WITH_QUERY && typeof url.search === DICT.string && url.search.length > 1) {
      fetchUrl += url.search;
    }

    try {
      return fetch(new Request(`${DICT.service.renderBase}${encodeURIComponent(fetchUrl)}${DICT.args.bot}${encodeURIComponent(userAgent)}`, {
        headers: headers,
        redirect: DICT.manual,
      }));
    } catch (fetchError) {
      console.warn('[CloudFlare Worker] [pre-rendering] [fetch] REDIRECT TO ostr.io FIALED WITH fetchError:', fetchError);
      return fetch(request);
    }
  }
};
```

## Fits when

- Cloudflare is already the CDN or proxy in front of the site.
- Origin is on AWS, Render, Fly, or any non-Vercel platform.
- You want bot management (Bot Score, IP Lists) for verification.

## Avoid when

- Site origin is on Vercel and Edge Middleware is sufficient (avoid double-proxy).
- You cannot afford the additional Workers request budget at your traffic volume.

## Common pitfalls

- **Worker timeouts on cold prerender** — Workers have a strict CPU and wall-clock budget. If the prerender source is cold (first request after deploy, or cache miss), it may exceed the timeout. Use cf.cacheTtl and warm the prerender cache for top routes.
- **Conflict with Cloudflare Cache Rules** — If Cache Rules cache the SPA HTML, bot requests may hit the cached SPA before the Worker can rewrite. Place the Worker before the cache layer or use Cache Rules bypass for crawler user-agents.
- **Bot Score not enabled by default** — Cloudflare Bot Management gives reliable verification but requires an Enterprise or Pro plan. Without it, fall back to user-agent + IP allowlist verification, which is good enough for major crawlers.

## Related

- [Bot Detection and Offloading via Prerendering](/blog/bot-detection-and-offloading-bot-visits.md)
- [Redirect Bot Traffic to Prerendering](/blog/redirect-bot-traffic-to-prerendering.md)
