Docs/Docs / JS Rendering

JavaScript Rendering

How numeric wait-based rendering works in fastCRW cloud and self-hosted deployments.

Published
March 11, 2026
Updated
March 11, 2026
Category
docs
Numeric waitFor semanticsNavigation lifecycle explainedAnti-bot warnings surfaced

How it works

When JS rendering is enabled, the renderer navigates to the page, waits for load completion, then applies numeric waitFor before extracting HTML.

There are two separate decisions here:

  • whether the page needs a browser at all,
  • and how long to wait after the page loads.

Example

{
  "url": "https://quotes.toscrape.com/js/",
  "renderJs": true,
  "waitFor": 2000
}

When To Turn It On

Enable JS rendering when the page content is not present in the initial HTML response. Typical examples:

  • single-page applications,
  • pages that fetch content after hydration,
  • and sites where the meaningful body is assembled client-side.

Do not enable it blindly for every request. HTTP-only fetches are faster and cheaper.

Important notes

  • waitFor is milliseconds.
  • warning may still appear if the rendered page is an anti-bot interstitial.
  • If you do not need browser rendering, keep renderJs off for lower latency.

Choosing a waitFor Value

Start with the smallest value that works:

  • 500 to 1000 for lightly hydrated pages,
  • 2000 for typical JS-heavy pages,
  • 3000 to 5000 only when you have confirmed the target hydrates slowly.

Long waits are not automatically safer. They increase latency and can hide the fact that the page is blocked rather than merely slow.

Cloud vs self-hosted

  • Cloud: JS rendering is always available. The managed infrastructure runs a LightPanda sidecar alongside the engine.
  • Self-hosted: You must run crw-server setup or configure a CDP browser (LightPanda, Chrome, or Playwright) in your config.toml under [renderer]. If no JS renderer is configured, requests with renderJs: true will fall back to HTTP-only fetching and include a warning.

What To Inspect in the Response

When rendered output looks wrong, check:

  • metadata.renderedWith to verify a browser was actually used,
  • metadata.elapsedMs to understand the cost of the request,
  • and warning to catch anti-bot or fallback situations.

Troubleshooting

  • Empty content from JS-heavy sites: Increase waitFor (e.g., 30005000). Some SPAs need extra time to hydrate.
  • rendered_with: "http_only_fallback" in metadata: JS rendering was requested but no renderer is available. Check your deployment configuration.
  • Internal error on renderJs: true: Verify the LightPanda sidecar is running and reachable. Check /api/health for renderer status.
  • Still poor output after increasing waitFor: The issue may be anti-bot protection or authentication flow, not rendering delay.