Skip to content
cccskills
FreePublished on GitHub

crawlberg-headless-fallback

Use when a static fetch returns nothing useful and the page needs a real browser. Covers `--browser-mode auto|always|never`, external CDP via `--browser-endpoint`, symptoms of JS-only pages and WAF blocks, and the performance cost.

The English summary is being prepared. Showing the original description.

xberg-io/crawlberg192 stars(GitHub 192 + cccskills 0)
Works withCloudflare

Run score Not tested

See how to install

Files included (2)

  • SKILL.md4.8 KB
  • index.md521 B

SKILL.md (original)

Review the instructions the agent will receive before you install.

<!-- AI-RULEZ :: GENERATED FILE — DO NOT EDIT Content-Hash: blake3:96b8fc624830e81d41d770e07bed8f15671042d9d84c5a4cee43604f06b23316 Source-Hash: blake3:4b18f96f8bf0da5fa02f0e2c5c6ad57db3a523b7eb72186f504977e42807760d Schema-Version: v1 -->

Headless fallback

Some pages are unscrapable without a real browser — SPA shells, infinite scroll, Cloudflare interstitials, JS-rendered article bodies. Crawlberg ships with an optional headless-Chrome backend driven by chromiumoxide.

Modes

--browser-mode auto    # default — try static first, fall back to browser on JS/WAF
--browser-mode always  # skip static, go straight to browser
--browser-mode never   # static only, fail closed

auto (default)

The engine fetches statically, then inspects the response. It launches headless Chrome and re-fetches when it sees:

  • WAF responses from one of 8 detected vendor fingerprints (Cloudflare, Akamai, AWS WAF, Imperva, DataDome, PerimeterX, F5, plus a generic catch-all).
  • SPA shells: <noscript> warnings, near-empty <body> with heavy JS.
  • Heuristic JS-render-required signals.

This is the right default. The browser only spins up when needed.

always

Skip the static probe entirely. Use when:

  • The user already told you the page needs JS.
  • You are scraping a site you know is React/Vue/Svelte SPA.
  • You need <script>-emitted state that never lands in static HTML.
crawlberg scrape https://spa.example.com --browser-mode always --format markdown

never

Static only — the browser path is disabled. Use when:

  • You are in a hot loop where a stray Chrome launch would blow the budget.
  • You are running in a sandbox without a Chrome binary.
  • The user explicitly wants only static fetches.

In never mode, JS-only pages return empty/stub content. Inspect markdown.content and markdown.warnings before treating the result as final.

Symptoms that point to headless

In --browser-mode never or when you suspect the auto detector missed a signal:

  • markdown.content is short, nav-only, or just a loading message.
  • status_code is 200 but metadata.headings is empty on a page that clearly has headings.
  • markdown.warnings mentions JS-render-required or WAF detection.
  • 403/406/503 with WAF response headers (server: cloudflare, cf-mitigated, x-amz-cf-id, set-cookie: __cf_bm=…).

Re-run with --browser-mode always. If that succeeds, leave it set for that host.

External CDP endpoint

Point at an already-running Chrome (Browserless, Steel, your own) instead of launching locally:

crawlberg scrape https://example.com \
  --browser-mode always \
  --browser-endpoint ws://browser.internal:9222/devtools/browser/<id> \
  --format markdown

The endpoint must be a WebSocket URL — ws:// or wss://. The CLI rejects anything else with a clear error.

Use external CDP when:

  • You are running in containers or CI without a local Chrome.
  • You want a shared, warm browser pool across many crawl jobs.
  • You need browser-side residential proxies or stealth configuration the local Chrome cannot provide.

Performance cost

Headless Chrome is expensive relative to a static fetch:

  • Cold start: 1-3 seconds the first time it launches.
  • Per-page overhead: 500 ms-2 s for NetworkIdle wait, plus the page's own JS load time.
  • Memory: each tab takes 100-300 MB; long crawls should bound --concurrent.

Mitigations:

  • Stay in --browser-mode auto — the engine only pays the cost when it needs to.
  • Use --browser-endpoint to share one warm browser across jobs.
  • Drop --concurrent when you know the crawl will route through Chrome.

Wait strategies

Pass via --config JSON when you need control:

crawlberg scrape https://example.com --browser-mode always \
  --config '{"browser":{"wait":"selector","wait_selector":".article-body"}}'

Supported strategies (the browser.wait field is a string enum; pair "selector" with a sibling wait_selector):

  • network_idle (default) — wait until the network goes quiet.
  • selector — wait until the CSS selector in wait_selector resolves.
  • fixed — wait a fixed duration.

extra_wait adds milliseconds on top of the wait strategy if the page keeps loading content after the primary signal.

Persistent profiles

crawlberg scrape https://app.example.com --browser-mode always \
  --config '{"browser_profile":"prod","save_browser_profile":true}'

Profile names are path-traversal-validated. Use them to keep cookies, localStorage, and login state across runs without re-authenticating.

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

api

Free

Use crawlberg api reference documentation.

The English summary is being prepared. Showing the original description.

xberg-io/crawlberg192Updated Oct 26, 2026

cli

Free

Use crawlberg cli reference documentation.

The English summary is being prepared. Showing the original description.

xberg-io/crawlberg192Updated Oct 26, 2026

Crawl, scrape, and convert websites to Markdown using the local crawlberg CLI and its MCP server. Use when the user wants to fetch a page, follow links across a domain, enumerate URLs, or drive a real browser. Covers installation, the subcommands (scrape, crawl, map, interact, batch-scrape, batch-crawl, download, citations, version, mcp, serve), output formats (JSON + Markdown), browser fallback, and when to prefer the MCP server over shelling out.

The English summary is being prepared. Showing the original description.

xberg-io/crawlberg192Updated Oct 26, 2026

Use when extracting a page needs scripted interaction first — click, type, press a key, scroll, wait, screenshot, or run JS before capturing the DOM. Covers `crawlberg interact URL --actions` with the real action schema, result shape, limits, and external-CDP options.

The English summary is being prepared. Showing the original description.

xberg-io/crawlberg192Updated Oct 26, 2026

Use when the user wants to follow links across a domain and capture every reachable page as Markdown. Covers `crawlberg crawl` with depth, page caps, concurrency, rate limiting, domain scoping, robots, and output selection.

The English summary is being prepared. Showing the original description.

xberg-io/crawlberg192Updated Oct 26, 2026

Use when the user wants the list of URLs on a site rather than the page content — sitemap analysis, link planning, or seeding another tool. Covers `crawlberg map URL` with `--limit`, `--search`, robots, output, and how it differs from a full crawl.

The English summary is being prepared. Showing the original description.

xberg-io/crawlberg192Updated Oct 26, 2026

See all skills by xberg-io

Report a problem with this skill