MCP server for web fetching and automation using Chromium headless browser.
I didn't wanna waste my "limited" tokens on Z.ai coding plan, therefore I made my own MCP to interact with the web, feel free to propose enhancements or new features.
- fetch_page: Fetch web pages and convert to markdown/HTML
- screenshot: Take screenshots of web pages or specific elements
- interact: Automate browser interactions (click, fill, scroll, wait)
- extract_data: Extract structured data using CSS selectors
- get_link: Get link information and follow redirects
# Clone the repository
git clone https://github.com/gzigurella/chromium-mcp.git
cd chromium-mcp
# Create virtual environment
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install the package
pip install -e .
# Install Chromium browser (required)
playwright install chromium# Clone and enter directory
git clone https://github.com/gzigurella/chromium-mcp.git
cd chromium-mcp
# Install with uv
uv pip install -e .
# Install Chromium
playwright install chromiumAdd to your ~/.config/opencode/opencode.json:
{
"mcpServers": {
"chromium-fetch": {
"type": "local",
"command": [
"/path/to/chromium-mcp/venv/bin/python",
"-m",
"chromium_mcp"
],
"enabled": true
}
}
}Add to your Claude Desktop config:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
Linux: ~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"chromium-fetch": {
"command": "/path/to/chromium-mcp/venv/bin/python",
"args": ["-m", "chromium_mcp"]
}
}
}For any MCP-compatible client:
# Start the server directly
/path/to/venv/bin/python -m chromium_mcpThe server communicates via stdio using the MCP protocol.
Fetch a web page and return content as markdown or HTML.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| url | string | Yes | - | URL to fetch |
| format | string | No | "markdown" | Output format: "markdown" or "html" |
| timeout | integer | No | 30 | Timeout in seconds |
| wait_for | string | No | null | CSS selector to wait for |
{
"url": "https://example.com",
"format": "markdown",
"timeout": 30,
"wait_for": ".main-content"
}Take a screenshot of a web page.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| url | string | Yes | - | URL to screenshot |
| format | string | No | "png" | Image format: "png" or "jpeg" |
| quality | integer | No | 80 | JPEG quality (1-100) |
| full_page | boolean | No | false | Capture full page |
| selector | string | No | null | CSS selector for element |
| timeout | integer | No | 30 | Timeout in seconds |
{
"url": "https://example.com",
"format": "png",
"full_page": true
}Interact with web page elements sequentially.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| url | string | Yes | - | URL to interact with |
| actions | array | Yes | - | List of actions |
| timeout | integer | No | 30 | Timeout in seconds |
Action Types:
click: Click element by selectorfill: Fill input fieldselect: Select dropdown optionscroll: Scroll pagewait: Wait for element
{
"url": "https://example.com/search",
"actions": [
{"type": "fill", "selector": "input[name='q']", "value": "test search"},
{"type": "click", "selector": "button[type='submit']"},
{"type": "wait", "selector": ".results", "milliseconds": 2000}
]
}Extract structured data using CSS selectors.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| url | string | Yes | - | URL to extract from |
| selectors | array | Yes | - | List of extraction rules |
| timeout | integer | No | 30 | Timeout in seconds |
{
"url": "https://example.com/products",
"selectors": [
{"name": "titles", "selector": "h2.product-title", "multiple": true},
{"name": "prices", "selector": ".price", "multiple": true},
{"name": "links", "selector": "a.product-link", "attribute": "href", "multiple": true}
]
}Get link href and text, optionally following navigation.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| url | string | Yes | - | URL of page containing link |
| selector | string | Yes | - | CSS selector for anchor |
| click | boolean | No | false | Follow the link |
| timeout | integer | No | 30 | Timeout in seconds |
{
"url": "https://example.com",
"selector": "a.download",
"click": true
}| Variable | Default | Description |
|---|---|---|
| CHROMIUM_PATH | auto | Path to Chromium executable |
| HEADLESS | true | Run browser in headless mode |
| TIMEOUT | 30 | Default operation timeout |
| DEBUG | false | Enable debug logging |
# Example
export TIMEOUT=60
export HEADLESS=false
python -m chromium_mcpsource venv/bin/activate
pytest
# With coverage
pytest --cov=src --cov-report=htmlchromium-mcp/
├── src/chromium_mcp/
│ ├── __init__.py
│ ├── __main__.py
│ ├── server.py
│ └── tools/
│ ├── __init__.py
│ ├── fetch_page.py
│ ├── screenshot.py
│ ├── interact.py
│ ├── extract_data.py
│ └── get_link.py
├── tests/
├── pyproject.toml
└── README.md
playwright install chromiumsudo sysctl -w kernel.shmmax=268435456export TIMEOUT=60file://URLs are blocked- Credentials are never logged
- Browser processes are always cleaned up
- All operations have configurable timeouts
MIT