codex-web-render · git:20260727.60d0582 · 2026-07-27 · sha256 3d61099eefebbe20

codex-web-render git:20260727.60d0582A

Immutable. This exact content is served forever at /api/v1/blob/3d61099eefebbe20.

---
name: codex-web-render
description: >-
  Fetch JavaScript-heavy, client-rendered, or bot-protected web pages that the
  built-in WebFetch tool cannot read (WebFetch returns an empty body, a loading
  spinner, an "enable JavaScript" notice, or just nav/boilerplate from an
  un-hydrated app shell). Drives a real system browser headless (no visible
  window, ~5-10s) and returns the page's fully rendered visible text, falling
  back to the Codex CLI only if that fails. Use this when the target URL matches
  the bundled problem-sites list (e.g. claude.ai/share links and other
  single-page apps), or when a WebFetch result for any URL comes back empty,
  truncated, or like an un-rendered SPA shell.
---

# Codex Web Render

Render JavaScript-heavy or bot-protected pages with a real browser and return
the page's visible text. This exists because the built-in `WebFetch` retrieves
raw HTML without executing JavaScript, so client-rendered pages come back as
empty shells.

The script has two paths:

1. **Fast path (default).** A pre-written Playwright renderer (`scripts/render.py`)
   drives a real system browser (Brave, then Chrome, then Chromium) in
   `--headless=new` mode with `--disable-blink-features=AutomationControlled`.
   No visible window opens, it takes ~5-10s, and that automation flag is what
   clears Cloudflare's non-interactive "checking your browser" challenge that
   plain headless Chromium gets blocked by.
2. **Codex fallback.** Only if the fast path fails (browser missing, still
   challenged, empty content) does it hand the URL to `codex exec`, which is far
   slower because it boots the full Codex agent to write and run its own browser
   script. Set `RENDER_NO_FAST=1` to force this path.

## When to use this skill

Use it in either of these cases:

1. **The URL is on the known problem list.** Before calling `WebFetch`, read
   `problem-sites.txt` in this skill's directory. If the target URL contains any
   pattern listed there, skip `WebFetch` entirely and render with Codex. The
   list is seeded with `claude.ai/share`.

2. **A `WebFetch` result looks un-rendered.** If you did call `WebFetch` and the
   result looks like an un-hydrated shell, fall back to Codex. Tell-tale signs:
   - Near-empty body, or only nav/footer boilerplate with no real content.
   - Text such as "You need to enable JavaScript to run this app".
   - A loading spinner / skeleton and none of the content you asked about.
   - The body is suspiciously short relative to what the page should contain.

## How to render

Run the bundled wrapper script with the URL. It prints the rendered visible
text to stdout:

```bash
bash ~/.claude/skills/codex-web-render/scripts/render-url.sh "<URL>"
```

Use the printed text as the page content for the rest of your task. The script
tries the fast Playwright path first and only escalates to Codex if it fails, so
a typical run is ~5-10s with no window. The first run may be a few seconds slower
while `uv` resolves the `playwright` package into its cache.

## Maintaining the problem-sites list

When you find a new domain that consistently returns an un-rendered shell from
`WebFetch`, offer to add it so future fetches skip straight to Codex. Append one
URL substring per line to:

```
~/.claude/skills/codex-web-render/problem-sites.txt
```

Match on the most specific stable path that identifies the problem (a bare
domain like `example.com`, or a path prefix like `example.com/app`).

## Prerequisites

- Fast path: `uv` on PATH, plus a real Chromium-based browser installed (Brave,
  Chrome, or Chromium). `uv` pulls in `playwright` on demand; no separate
  browser download is needed because it reuses the system browser binary.
- Fallback path: the Codex CLI installed and authenticated (`npm i -g
  @openai/codex` then `codex login`). Only needed if the fast path can't render.
  The script runs `codex exec --dangerously-bypass-approvals-and-sandbox` so the
  run is unattended.

## Notes and limitations

- The fast path is windowless and free; the Codex fallback spends Codex
  usage/credits and is much slower. Only reach for this skill when `WebFetch`
  can't do the job.
- It renders a single page's text. It does not log in, click through flows, or
  bypass paywalls or auth walls. It uses a throwaway browser profile, so a page
  needing your session returns whatever a logged-out browser sees.
- Output is the page's visible text, not raw HTML or structured data.