cute-web-scraper
cute-web-scraper
MCP-сервер, который даёт Claude возможность парсить веб-страницы. Бесплатно, локально, без API-ключа и облачного аккаунта.
Спрашивайте на обычном английском. Он загружает страницы, при необходимости рендерит JavaScript, обходит блокировки и возвращает чистый Markdown или таблицу, к которой можно обращаться с запросами — без селекторов и склеивающего кода.
Почему именно этот
Он пробивается. Четыре эскалирующих уровня — обычный HTTP, отпечатки браузера, настоящий браузер, затем скрытый браузер. ASOS, eBay, Booking.com и Trustpilot отдают реальные данные с домашнего подключения без прокси.
Он не тратит ваш контекст. Статьи очищаются от навигации, баннеров с cookie и подвалов: страница новостей BBC сокращается с 20 513 символов до 3 198. Большие результаты попадают в таблицу SQLite, к которой вы обращаетесь через SQL, а не вставляете в чат.
Он честно говорит о сбоях. Пять из протестированных сайтов отдали отказ под успешным статусом — интерстициальную страницу под HTTP 200, проверку на бота под 202 — а один отдал реальный контент под 403. Определение блокировки оценивает тело страницы, а не код статуса, так что заглушка не выдаётся за данные.
Целые сайты, а не отдельные страницы. Обнаружение sitemap, параллельная загрузка и 24 инструмента для товаров, контактов, каталогов Shopify, мест, PDF и отслеживания изменений.
Установка
pipx install git+https://github.com/maccydee/cute-web-scraperChromium загружается автоматически при первом использовании js_render (одноразово, ~130 МБ).
Related MCP server: mcp-server-scraper
Подключение к Claude Code
claude mcp add cute-web-scraper -- cute-web-scraperЗатем просто спросите:
Scrape every product from https://example-shop.com and give me a CSV of name and price.Инструменты
Загрузка и обнаружение
Инструмент | Что делает |
| Поиск в интернете с ранжированными результатами — вход, когда у вас вопрос, а не URL |
| Один URL в чистый Markdown, с заголовком, статусом и количеством ссылок |
| Сообщает об API-вызовах страницы с их JSON — читайте источник данных напрямую |
| Много URL параллельно, возвращает результаты и ошибки по каждому URL |
| Обнаруживает страницы сайта через sitemap, при отсутствии — переход по ссылкам |
| Определяет платформу, находит sitemap, сообщает, нужен ли JavaScript |
Извлечение
Инструмент | Что делает |
| Произвольные поля через CSS-селекторы — превращает любой список в таблицу |
| Структурированные данные о товарах (название, цена, валюта, наличие, бренд, артикул, рейтинг) из JSON-LD, OpenGraph или микроразметки |
| Адреса электронной почты по списку URL, с окружающим контекстом |
| Номера телефонов по списку URL, с окружающим контекстом |
| Все гиперссылки, преобразованные в абсолютные URL |
| Профили в социальных сетях на восьми платформах |
| Весь каталог Shopify, по одной строке на вариант товара |
| Коллекции магазина Shopify и количество товаров в них |
Места и местный бизнес
Инструмент | Что делает |
| Поиск по названию или описанию — название, адрес, координаты, телефон, сайт, часы работы |
| Все заведения категории в радиусе от места |
Отслеживание изменений
Инструмент | Что делает |
| Загружает страницу и сравнивает с последней проверкой — новое, то же или изменено |
| Отслеживаемые страницы и время последнего просмотра каждой |
| Прекратить отслеживание страницы |
Таблицы результатов
Инструмент | Что делает |
| Сохранённые таблицы результатов с количеством строк и колонок |
| Колонки таблицы, количество строк и пример |
| Только чтение SQL по сохранённой таблице — фильтрация, агрегация, группировка, сортировка, при желании сохранение результата в новую таблицу |
| Запись таблицы в CSV или JSON на диск |
| Удаление сохранённой таблицы |
Типичный запуск объединяет их: analyze_website → crawl_site → fetch_pages → query_table.
Извлечение произвольных полей
extract_by_selector покрывает всё, что не делают фиксированные экстракторы:
Get the title, price and link from every product on these 40 pages,
save it as `catalogue`, then show me anything under £50.fields сопоставляет имена колонок с CSS-селекторами. row_selector превращает каждое совпадение в строку — именно это превращает список в таблицу. Суффикс @attr читает атрибут вместо текста, при этом href и src преобразуются в абсолютные URL:
{"name": "h3 a@title", "price": ".price_color", "link": "h3 a@href"}Управление страницей
fetch_page принимает actions, которые выполняются до чтения страницы — cookie-заглушки, кнопки «показать ещё», бесконечная прокрутка и формы поиска:
[{"action": "click", "selector": "#accept-cookies"},
{"action": "scroll_to_bottom", "max_rounds": 10}]Доступные действия: click, type, press, wait, wait_for, scroll, scroll_to_bottom и click_until_gone. Каждое сообщает, что оно сделало, так что шаг, который молча ничего не нашёл, виден, а не оставляет вас в догадках.
Чтение API вместо страницы
Когда сайт сложно парсить, inspect_network рендерит его и сообщает о выполненных запросах. Страница на JavaScript почти всегда загружает данные с конечной точки, которую можно запросить напрямую — это дешевле, чем разбор разметки, и переживает редизайны, ломающие селекторы:
Inspect the network on this listing page, then fetch whatever JSON endpoint it uses.Отслеживание изменений
Check https://example.com/pricing for changes.track_changes сохраняет снимок и сообщает new, same или changed с объединённым diff. Это мониторинг без планировщика — проверяйте, когда хотите, и видите только разницу.
Слэш-команды
Сервер поставляется с четырьмя готовыми рабочими процессами, которые появляются как слэш-команды в Claude Code: scrape_site, scrape_shopify_store, find_contacts и compare_prices.
Работа с большими объёмами данных
Любой инструмент, возвращающий строки, принимает save_as. Вместо помещения данных в разговор он записывает таблицу результатов и возвращает сводку:
Extract the whole catalogue from deathwishcoffee.com into a table called `catalogue`,
then tell me the price range and how many variants are out of stock.Claude вызывает extract_shopify_store(save_as="catalogue"), получает количество строк и список колонок, а затем отвечает через query_table:
SELECT COUNT(*) AS variants, MIN(price) AS cheapest,
MAX(price) AS dearest, SUM(available) AS in_stock
FROM catalogueТаблица может содержать 100 000 строк, и ни одна из них не попадает в разговор. query_table строго только для чтения — он работает с read-only дескриптором SQLite и отклоняет всё, что не является SELECT, так что запрос никогда не может изменить или удалить сохранённые данные.
Таблицы хранятся в файле SQLite по пути ~/.cute-web-scraper/results.db (задайте SCRAPER_DB_PATH, чтобы переместить его).
Очистка данных
query_table также принимает save_as, который сохраняет результат как новую таблицу. SQL уже выражает обычные операции очистки, поэтому отдельного набора инструментов редактирования нет:
SELECT DISTINCT * FROM leads -- deduplicate
SELECT street || ', ' || city AS address FROM leads -- merge columns
SELECT name, phone FROM leads WHERE phone IS NOT NULL -- drop columns and rows
SELECT vendor AS brand FROM catalogue -- renameИсходная таблица остаётся нетронутой, если вы намеренно не укажете её собственное имя, а ответ сообщает replaced_existing_table, когда вы это делаете — так что фильтрация на месте никогда не приводит к молчаливой потере строк.
Места и местный бизнес
find_places ищет одно место; find_places_nearby возвращает всё заведения категории в радиусе — это случай генерации локальных лидов:
Find every dentist within 4km of Bath, save it as `leads`,
then tell me how many have a website but no phone number.Категории принимают понятные названия (cafe, dentist, hotel, solicitor, gym, hairdresser, …) или сырой тег OpenStreetMap, например amenity=dentist.
Примечание об источнике данных. Это OpenStreetMap, а не Google Maps. Google был очевидной целью, но он не работает: автоматизированный браузер получает интерстициальную страницу согласия на cookie, а после её обхода — урезанную карту без панели мест. Скрытый уровень не помогает, потому что это стена согласия, а не обнаружение бота — другая проблема, не та, которую решает скрытие.
OpenStreetMap даёт те же поля — название, адрес, координаты, телефон, сайт, часы работы, категорию — через документированные открытые конечные точки без ключа. Единственное, чему нет аналога, — это звёздные рейтинги и количество отзывов, которые являются собственными проприетарными данными Google.
Обе конечные точки управляются волонтёрами. Политика Nominatim «один запрос в секунду» соблюдается внутренне независимо от SCRAPER_DELAY_MS, а запросы Overpass проходят через несколько публичных зеркал, потому что основной инстанс регулярно возвращает 504 под нагрузкой.
Вывод инструментов также ограничен SCRAPER_MAX_INLINE_CHARS (по умолчанию 25 000). После этого результат усекается с примечанием, указывающим на save_as — так что один вызов не может случайно заполнить ваш контекст.
Примеры запросов
Export the whole catalogue from deathwishcoffee.com and tell me the price range.
Find all email addresses on https://company.com and its contact pages.
What platform is https://myblog.com on? Does it need JavaScript to scrape?
Scrape these 200 product pages into a table, then show me everything under £50 that's in stock.
Extract the social media links from these 10 agency sites: [urls...]Конфигурация
Всё настраивается переменными окружения, с значениями по умолчанию, работающими без настройки.
Variable | Default | Meaning |
|
| Базовая задержка между запросами к одному домену |
|
| Максимальное количество параллельных запросов |
|
| Как долго полученная страница остаётся пригодной для повторного использования |
|
| Кэшированные страницы до вытеснения по принципу наименее недавно использованных |
| unset | Bearer-токен для HTTP-режима |
| unset | Профиль Chrome для наследования авторизованных сессий |
|
| Повторять заблокированные запросы с TLS-отпечатками браузера |
|
| Скрытый браузер последней надежды для самых сложных блокировок |
|
| Где хранятся таблицы результатов |
|
| Потолок объёма, который один инструмент возвращает инлайн |
Для пакетной обработки длинного списка URL в одну таблицу требуется mode: "append" при каждом вызове после первого, иначе каждый пакет заменяет предыдущий. Страницы, которые возвращаются неполными, можно снабдить параметром wait_ms или, лучше, wait_for с CSS-селектором.
Как это работает
Основное содержимое, а не вся страница. Страницы, имеющие форму статьи, обрабатываются через trafilatura, который выделяет тело и отбрасывает окружающее оформление — выбрано потому, что на независимом бенчмарке из 2 008 страниц он набирает 0,791 F1 против 0,674 у Readability. Он применяется постранично, а не универсально: тот же бенчмарк показывает расхождение экстракторов на 20–30 пунктов на сетках товаров и подборках, где «основное содержимое» — не статья, поэтому страницы-списки сохраняют полный документ. Передайте main_content: false, чтобы принудительно применить это где угодно.
Четыре уровня, эскалация только при отказе. Обычный HTTP-клиент обрабатывает большинство страниц. Если сайт отказывает, запрос повторяется с настоящими TLS-отпечатками браузера (Chrome, затем Safari), потому что некоторые сайты снимают отпечаток самого TLS-рукопожатия, и никакое изменение заголовков не помогает. js_render: true выполняет рендеринг в Chromium для одностраничных приложений. В крайнем случае браузер со скрытыми патчами обрабатывает сайты, которым нужен JavaScript и которые отклоняют обычную автоматизацию.
Каждый уровень устраняет свой тип сбоя, и ни один не является надмножеством других: TLS-уровень не может выполнять JavaScript, а Playwright — обнаруживаемый автоматизированный браузер. Каждый результат сообщает, какой уровень его обслужил. Установите SCRAPER_IMPERSONATE=0 или SCRAPER_STEALTH=0, чтобы отключить последние два и оставить блокировки как есть.
Последние два уровня — это обход, а не вежливость: они существуют, чтобы обойти защиту от ботов, которую сайты намеренно развернули. Они запускаются только после отказа, никогда на сайте, который нормально отдал страницу.
Адаптивная экспоненциальная задержка. Запросы к одному домену разнесены на SCRAPER_DELAY_MS, измеряемую от начала до начала, поэтому задержка ограничивает скорость запросов, а не добавляется к медленным ответам. Когда домен сопротивляется — 429, 403, вызов Cloudflare — задержка для этого домена удваивается, вплоть до 60 секунд, и снижается, когда запросы снова начинают проходить. Домены отслеживаются независимо, поэтому одновременный сбор данных с двух сайтов не требует дополнительных затрат.
robots.txt не применяется. Он читается только для поиска карт сайта; его правила Disallow не учитываются, и нет настройки, чтобы это изменить. Адаптивная задержка по доменам — это механизм вежливости данного инструмента.
Короткий кэш. Полученные страницы переиспользуются в течение пяти минут, поэтому запуск fetch_pages, а затем extract_emails по одним и тем же URL не приводит к повторной загрузке всего.
HTTP-режим
По умолчанию используется stdio, именно его использует claude mcp add выше. Чтобы запустить постоянный общий экземпляр, вместо этого:
SCRAPER_AUTH_TOKEN=$(openssl rand -hex 16) cute-web-scraper --http --port 8080claude mcp add --transport http cute-web-scraper http://127.0.0.1:8080/mcpОн привязывается к 127.0.0.1 и предоставляет /mcp, а также конечную точку /health. Привязка за пределами loopback требует SCRAPER_AUTH_TOKEN, и сервер отказывается запускаться без него, а не тихо публикует открытый скрапер в вашей сети.
Ограничения
Нет ротации прокси и решения CAPTCHA. Сайт, переживший все четыре уровня, помечается как заблокированный, а не угадывается.
LinkedIn и подобные могут потребовать указать
SCRAPER_CHROME_USER_DATA_DIRна авторизованный профиль Chrome.SCRAPER_DELAY_MS=0убирает вежливую задержку, но экспоненциальная задержка всё равно срабатывает, когда сайт сопротивляется.Извлечение телефонов намеренно консервативно: требуется код страны или префикс магистрали, поэтому пропускаются некоторые простые локальные форматы, но не возвращаются годы и номера заказов.
Разработка
uv sync --extra devuv run pytest -vuv run pytest -m integration -v -suv run ruff check src/ tests/ && uv run mypy src/cute_web_scraper/Модульные тесты герметичны и никогда не обращаются к сети. Интеграционные тесты обращаются к живым сайтам и исключены из запуска по умолчанию.
Лицензия
MIT — см. LICENSE.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceAn MCP server for web content extraction that converts HTML pages into clean, LLM-optimized Markdown using Mozilla's Readability. It supports batch processing, intelligent multi-page crawling, and configurable caching while respecting robots.txt standards.51
- AlicenseAqualityCmaintenanceMCP server for web scraping — extract clean markdown, links, and metadata from any URL. Free Firecrawl alternative.5935MIT
- AlicenseNot gradedqualityCmaintenanceOpen-source web scraper and extraction MCP server with JavaScript rendering, markdown output, PDF/DOCX parsing, structured errors, and validated extraction contract diagnostics for agents.2AGPL 3.0
- AlicenseNot gradedqualityAmaintenanceRemote MCP server for web scraping with anti-bot evasion. Provides stealth HTTP fetching, headless browser with Cloudflare bypass, CSS selectors, YouTube transcripts, and Markdown conversion.1MIT
Related MCP Connectors
All HasData scraping tools in one MCP server: Google, TikTok, Instagram, maps, e-commerce and more.
One MCP server for 180+ live web-data APIs returning clean JSON from sites that block scrapers.
Firecrawl MCP — wraps the Firecrawl API (firecrawl.dev) for web
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/maccydee/cute-web-scraper'
If you have feedback or need assistance with the MCP directory API, please join our Discord server