Browser Rendering
Browser Markdown Scrape
Convert any URL to Markdown or scrape CSS with Browser Rendering quickAction - JS-rendered pages to clean text for LLMs
Convert a URL to Markdown and scrape CSS selectors using Cloudflare Browser Rendering quickAction (REST-style binding - not Puppeteer).
Features
GET /markdown?url=→ page Markdown viaquickAction("markdown")GET /scrape?url=&selector=→ structured elements viaquickAction("scrape")- HTTP/HTTPS URL validation only
API Reference
GET /markdown
url string (required)
Target page (http:// or https://).
Example Request
curl "https://your-worker.workers.dev/markdown?url=https://example.com"Success Response
{
"url": "https://example.com/",
"markdown": "# Example Domain\n\n..."
}Error Codes
400- Missing or non-http(s) url (INVALID_URL)502- quickAction failure (MARKDOWN_ERROR)
GET /scrape
url string (required)
Target page.
selector string (required)
CSS selector (sent as one scrape element).
Example Request
curl "https://your-worker.workers.dev/scrape?url=https://example.com&selector=h1"Success Response
{
"url": "https://example.com/",
"results": [
{
"selector": "h1",
"results": [{ "text": "Example Domain", "html": "Example Domain" }]
}
]
}Error Codes
400- Invalid url (INVALID_URL)400- Missing selector (MISSING_SELECTOR)502- quickAction failure (SCRAPE_ERROR)
Use Cases
- Normalize pages to Markdown for RAG / LLM pipelines
- Extract specific DOM fields without writing Puppeteer scripts
- Compare quickAction REST bindings vs Puppeteer-based experiments
Limitations
- Requires Browser Rendering (often
wrangler dev --remotelocally) - Single CSS selector per scrape request
- JS-heavy SPAs may need advanced goto options (not exposed in this demo)
Use in your project
Copy these files into an existing Worker. Prefer Deployment to try the full experiment first. Source: apps/experiments/browser-markdown-scrape.
DependenciesNoneBindingsBrowser RenderingPlatformWorkers runtime
import type { BrowserRun } from "../types/env";import type { QuickActionPayload } from "../types/browser";function isResponse(value: unknown): value is Response { return ( typeof value === "object" && value !== null && typeof (value as Response).json === "function" && typeof (value as Response).ok === "boolean" );}/** * Call Browser Rendering quickAction and normalize Response or result object to a payload. */export async function runQuickAction( browser: BrowserRun, action: "markdown" | "scrape", params: Record<string, unknown>): Promise<QuickActionPayload> { const raw = await browser.quickAction(action, params); if (isResponse(raw)) { let body: QuickActionPayload; try { body = (await raw.json()) as QuickActionPayload; } catch { throw new Error(`Browser ${action} returned non-JSON response`); } if (!raw.ok || body.success === false) { throw new Error(body.error ?? `Browser ${action} failed (${raw.status})`); } return body; } if (raw.success === false) { throw new Error(typeof raw.result === "string" ? raw.result : `Browser ${action} failed`); } return raw;}export function extractMarkdown(payload: QuickActionPayload): string { const { result } = payload; if (typeof result === "string") return result; if ( result && typeof result === "object" && "markdown" in result && typeof (result as { markdown: unknown }).markdown === "string" ) { return (result as { markdown: string }).markdown; } throw new Error("Browser markdown response missing result string");}export function extractScrapeResults(payload: QuickActionPayload): unknown { const { result } = payload; if (Array.isArray(result)) return result; if ( result && typeof result === "object" && "results" in result && Array.isArray((result as { results: unknown }).results) ) { return (result as { results: unknown[] }).results; } throw new Error("Browser scrape response missing results array");}Deployment
Confirm browser binding
wrangler.json declares "browser": { "binding": "BROWSER" }.
Test your deployment
curl "https://your-worker.workers.dev/markdown?url=https://example.com"Local Development
cd apps/experiments/browser-markdown-scrape
npm install
npm run dev -- --remotecurl "http://localhost:8787/markdown?url=https://example.com"Configuration
- Browser binding
BROWSER- usesquickAction("markdown" | "scrape", …)
Cloudflare Features Used
- Workers - Edge compute runtime
- Browser Rendering - Headless browser at the edge
- Markdown endpoint - URL → Markdown quick action
- Scrape endpoint - CSS selector scrape quick action