Skip to main content
Glama
bidouilles

cloudflare-crawl-mcp

by bidouilles
README.md
# cloudflare-crawl-mcp

MCP server for [Cloudflare Browser Rendering Crawl API](https://developers.cloudflare.com/browser-rendering/rest-api/crawl-endpoint/). Fetches and crawls web pages, returning clean Markdown optimized for LLM consumption.

Built with [FastMCP](https://github.com/jlowin/fastmcp) and [uv](https://github.com/astral-sh/uv).

## Tools

| Tool | Description |
|------|-------------|
| `scrape_url` | Fetch a single page as Markdown. The primary tool — use this when you know the URL. |
| `map_url` | Discover URLs on a site without fetching content. Use to find the right page first. |
| `crawl_url` | Crawl multiple pages and return all content as Markdown. |

**Typical workflow:** `map_url` to find pages → `scrape_url` to read the right one.

## Prerequisites

1. A Cloudflare account with [Browser Rendering](https://developers.cloudflare.com/browser-rendering/) enabled
2. An API token with **Account > Browser Rendering > Edit** permission ([create one here](https://dash.cloudflare.com/profile/api-tokens))
3. [uv](https://docs.astral.sh/uv/getting-started/installation/) installed

## Configuration

| Variable | Required | Description |
|----------|----------|-------------|
| `CF_API_TOKEN` | Yes | Cloudflare API token |
| `CF_ACCOUNT_ID` | Yes | Cloudflare Account ID |
| `CF_RATE_LIMIT` | No | API requests per minute (default: `6` for Free, set to `600` for Paid) |

## Setup

### Claude Code

```bash
claude mcp add cloudflare-crawl \
  -e CF_API_TOKEN=your_api_token \
  -e CF_ACCOUNT_ID=your_account_id \
  -- uv run --directory /path/to/cloudflare-crawl-mcp python server.py
```

### Codex

```bash
codex mcp add cloudflare-crawl \
  -- env CF_API_TOKEN="your_api_token" CF_ACCOUNT_ID="your_account_id" \
  uv run --directory /path/to/cloudflare-crawl-mcp python server.py
```

### Claude Desktop

Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):

```json
{
  "mcpServers": {
    "cloudflare-crawl": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/cloudflare-crawl-mcp", "python", "server.py"],
      "env": {
        "CF_API_TOKEN": "your_api_token",
        "CF_ACCOUNT_ID": "your_account_id"
      }
    }
  }
}
```

### Cursor

Add to `.cursor/mcp.json` in your project or `~/.cursor/mcp.json` globally:

```json
{
  "mcpServers": {
    "cloudflare-crawl": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/cloudflare-crawl-mcp", "python", "server.py"],
      "env": {
        "CF_API_TOKEN": "your_api_token",
        "CF_ACCOUNT_ID": "your_account_id"
      }
    }
  }
}
```

## Tool Reference

### `scrape_url`

Fetch a single page and return its content as Markdown.

```
url (string, required)    — The URL to fetch
render (boolean, optional) — Render JavaScript with headless browser (default: true, set false for static pages)
```

### `map_url`

Discover URLs on a website without fetching full content.

```
url (string, required)                  — Starting URL
limit (number, optional)                — Max URLs to discover (default: 50)
depth (number, optional)                — Link depth to follow (default: 2)
include_subdomains (boolean, optional)  — Follow subdomain links (default: false)
include_external_links (boolean, optional) — Follow external links (default: false)
include_patterns (string[], optional)   — Only visit matching URLs (e.g. "https://example.com/docs/**")
exclude_patterns (string[], optional)   — Skip matching URLs
```

### `crawl_url`

Crawl multiple pages and return all content as Markdown.

```
url (string, required)                  — Starting URL
limit (number, optional)                — Max pages to crawl (default: 10)
depth (number, optional)                — Link depth (default: 1)
include_subdomains (boolean, optional)  — Follow subdomain links (default: false)
include_external_links (boolean, optional) — Follow external links (default: false)
include_patterns (string[], optional)   — Only visit matching URLs
exclude_patterns (string[], optional)   — Skip matching URLs
render (boolean, optional)              — Render JavaScript (default: true)
```

## Cloudflare Plan Limits

| | Free | Paid |
|---|---|---|
| Browser time | 10 min/day | 10 hrs/month |
| API rate limit | 6 req/min | 600 req/min |
| Concurrent browsers | 3 | 10 |
| Max pages per job | 100,000 | 100,000 |
| Max job duration | 7 days | 7 days |
| Results available | 14 days | 14 days |

`render: false` crawls run on Workers instead of a headless browser and do not consume browser time.

## License

MIT

TDQS

A4.9/5.0

Scored across 3 tools

Disambiguation5/5

Each tool has a clear, distinct purpose: scrape_url fetches one page, map_url discovers URLs without fetching content, and crawl_url fetches multiple pages. The descriptions explicitly state when to use each, so there is no ambiguity.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern with underscores: scrape_url, map_url, crawl_url. The style is uniform and predictable, making it easy to infer functionality.

Tool Count5/5

Three tools is well-scoped for a crawling server. Each tool covers a distinct core operation—single fetch, URL discovery, and bulk crawl—without unnecessary redundancy or bloat.

Completeness4/5

The tools cover the essential crawl lifecycle: discover URLs, scrape a single page, and crawl multiple pages. Minor gaps exist (e.g., no sitemap parsing or headless options for custom headers), but the core workflows are complete.

Maintenance

ActivityInactive
ResponsivenessNo issues