Iskalo (Искало)
Search the Russian web with city, contact and provider filters, retrieve indexed page content, and use semantic reranking through a hosted MCP server.
Server MCP Terhosting
npx add-mcp 'https://iskalo.ru/mcp'Terpasang ke Claude Code, Codex, Cursor, dan lainnya
Dokumentasi
API и MCP для ИИ-агентов
Искало — собственный индекс русскоязычного интернета. Поиск отдаёт не только ссылки, но и профиль сайта: телефоны, e-mail, город, соцсети, ИНН и год последнего обновления. Оплата в рублях, без VPN и иностранных карт.
— в личном кабинете: вход по коду на почту, ключ сразу, без звонков и договоров. Каждый месяц 300 ₽ на запросы — бесплатно, дальше — пополнение картой или СБП. Там же баланс, расход по дням и ключи для каждого проекта.
Цены
| Операция | Цена |
|---|---|
Поиск /v1/search, до 50 результатов с профилем сайта | 0,30 ₽ за запрос |
… с полным текстом страниц (include_content) | +0,05 ₽ за результат, не больше +0,30 ₽ |
Профиль сайта /v1/site/{host} | 0,10 ₽ |
Текст страницы /v1/contents | 0,10 ₽ за адрес |
Нейроответ с источниками /v1/answer | 2 ₽ |
Пачка queries до 20 запросов | как отдельные запросы |
Деньги списываются до выполнения и возвращаются, если запрос не выполнился. Ошибки 400, 401, 404 и 429 бесплатны.
Быстрый старт: curl
curl -s https://iskalo.ru/v1/search \
-H "Authorization: Bearer $ISKALO_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "кавер-группа Казань", "limit": 20,
"filters": {"has_phone": true, "exclude_domains": ["leadbook.ru"]}}'
Ответ (сокращён):
{
"query": "кавер-группа казань", "mode": "hybrid", "mode_used": "classic",
"semantic_rerank_used": true, "semantic_rerank_reason": null,
"semantic_coverage": {"matched_vectors": 72, "candidates": 300},
"page": 1, "limit": 20, "has_more": true,
"total_estimate": 214, "total_is_lower_bound": false, "candidates_cap": 300,
"warnings": ["neural_off"],
"warning_text": {"neural_off": "векторный отбор кандидатов не использован; смысловая переранжировка показана отдельно"},
"results": [{
"title": "Кавер-группа …", "url": "https://example.ru/", "host": "example.ru",
"snippet": "…", "score": 0.81,
"profile": {"phones": ["+79870000000"], "emails": ["band@example.ru"],
"socials": {"vk": "https://vk.com/…"}, "city": "Казань",
"inn": null, "org": null, "year": 2025}
}],
"cost_rub": 0.3
}
Python
Готовый клиент — один файл без зависимостей: tools/iskalo_client.py в репозитории. Кэш ответов на диске, темп, повторы по Retry-After, пачки и обход всех страниц.
from iskalo_client import Iskalo
isk = Iskalo() # ключ — из переменной ISKALO_KEY
for hit in isk.search_all("ведущий на свадьбу Пермь", filters={"has_phone": True}):
print(hit["host"], hit["profile"]["phones"])
for r in isk.batch(["фокусник Омск", "фокусник Тюмень"], limit=50):
print(r["query"], len(r.get("results", [])))
print(isk.site("av55.ru")["profile"])
Без клиента — обычный httpx или requests:
import httpx
r = httpx.post("https://iskalo.ru/v1/search", json={"query": "фаер-шоу Самара"},
headers={"Authorization": "Bearer " + KEY}, timeout=60)
if r.status_code == 429:
time.sleep(int(r.headers["Retry-After"]))
MCP для Claude Code и других агентов
Сервер MCP — https://iskalo.ru/mcp (Streamable HTTP). Подключение в Claude Code:
claude mcp add --transport http iskalo https://iskalo.ru/mcp \
--header "Authorization: Bearer msk_…"
Или в .mcp.json проекта:
{"mcpServers": {"iskalo": {"type": "http", "url": "https://iskalo.ru/mcp",
"headers": {"Authorization": "Bearer ${ISKALO_KEY}"}}}}
Инструменты: web_search (те же параметры и фильтры, что у REST), site_profile, get_contents, answer, usage. Ошибка инструмента — например, «пополните баланс» — приходит модели текстом.
Методы
| Метод | Что делает |
|---|---|
POST /v1/search | Поиск. Один запрос — query, пачка — queries |
GET /v1/site/{host} | Профиль сайта: контакты, город, соцсети, год, страниц в индексе. 404 — сайта нет в индексе (бесплатно) |
POST /v1/contents | Текст страниц из индекса: {"urls": [...]}, до 20 адресов |
POST /v1/answer | Короткий ответ со ссылками [1], [2]: {"query": "..."} — на платном тарифе (с первого пополнения); на бесплатном — 403 без списания |
GET /v1/usage | Баланс, бесплатный остаток, расход за месяц — по операциям и по каждому ключу |
GET /v1/keys, POST /v1/keys, DELETE /v1/keys/{key_id} | Ключи аккаунта с метками: {"label": "katalog-artistov"} выпускает ещё один ключ — отдельный на проект или сессию агента, чтобы видеть, кто сколько потратил |
GET /v1/prices | Прайс и лимиты, без ключа |
POST /v1/billing/topup | Пополнение: {"amount_rub": 500} → ссылка на оплату |
Параметры поиска
| Поле | Значение |
|---|---|
query | Запрос, до 400 символов |
limit | Результатов на странице, 1–50, по умолчанию 10 |
page | Страница, 1–30. Есть ли следующая — поле has_more |
mode | hybrid (по умолчанию), neural, classic. Отбор кандидатов — mode_used, смысловая переранжировка — semantic_rerank_used |
autocorrect | Исправлять опечатки и раскладку, по умолчанию да. Исходный запрос — в corrected_from; с false — подсказка в did_you_mean |
include_content | Добавить полный текст страниц (доплата, см. цены) |
fields | Какие поля профиля вернуть: phones, emails, socials, city, inn, org, year. По умолчанию все, [] — без профиля |
filters.has_phone, filters.has_email | Только сайты с телефоном / e-mail |
filters.require_any_contact | Есть телефон, e-mail или соцсеть в сохранённом профиле. Это не проверка актуальности или владельца контакта. |
filters.provider_type | Тип по заголовку и описанию страницы: performer, speaker, talent_agency, venue_operator, event_agency, conference_organizer, costume_shop, education, equipment_vendor, other_business, unknown. Необязательный строгий фильтр: при его включении неизвестные типы отсекаются. |
filters.city | Город сайта по профилю: «Казань» |
filters.fresh_since | Сайт обновлялся не раньше этого года: 2024 |
filters.include_domains, filters.exclude_domains | Искать только на этих сайтах / без них, до 100 доменов |
filters.site_type | direct — без каталогов и агрегаторов; тип поставщика задаётся отдельно, catalog — только они |
Операторы в query | "точная фраза", -слово, site:домен, -site:домен |
queries | Пачка до 20 запросов: строки или объекты с теми же полями. Общие поля запроса действуют на все. Ответ — responses в том же порядке |
Что в ответе
profile— то, что робот нашёл на главной сайта.year— самый свежий год: из текста главной или из sitemap. Пустые поля —[]илиnull.site_type—catalog, если сайт похож на каталог или агрегатор, иначеdirect. Отсечь каталоги в выдаче —filters.site_type: "direct".relevance— эвристические признаки по метаданным страницы:provider_type,provider_type_source,query_intent,intent_reason,page_city,city_conflict. Упоминание города в заголовке не подтверждает адрес или город базирования. Несовпадение роли с запросом и явное противоречие города понижают результат; неизвестный тип сам по себе не штрафуется.filter_diagnostics— счётчики выбранного пула (scope: retrieved_candidates), а не всего индекса:candidates,after_contact,after_city,after_site_type,after_provider_type,before_dedup,after_dedup. Этапы последовательны: контакт считается после исключения запрещённых сайтов и доменных фильтров; между типом поставщика и дедупом также действуют текстовая релевантность и год обновления.score— только для сортировки внутри одного запроса. Сравнивать его между запросами нельзя, бывает больше 1.total_estimate— сколько результатов можно пролистать. Лексический отбор ограниченcandidates_cap: обычно 300, с фильтрами 800; отдельный векторный отбор может добавить кандидатов, поэтому совпадений в индексе может быть больше; тогдаtotal_is_lower_bound: true. Полеtotalоставлено для совместимости, оно равноtotal_estimate.mode_usedиneuralописывают отбор кандидатов. Приclassicкандидаты лексические; отдельная переранжировка по векторам работает и приMS_NEURAL=0.semantic_rerank_usedподтверждает её выполнение для запроса; при пропускеsemantic_rerank_reasonсодержит причину (disabled, no_candidates, vectors_missing, encoder_unavailable, vectors_error, no_vectors, invalid_vectors). При векторном отборе причина — neural_used. Ответ из кэша сохраняет статус исходного вычисления.semantic_coverage:matched_vectors— число кандидатов с собственным вектором,candidates— размер пула переранжировки (до 300, до склейки и пагинации). При fallback matched_vectors=0. У результатаsemantic_vector_matched: falseозначает медиану, true — собственный вектор; отсутствие поля — результат не участвовал в отдельной переранжировке (в том числе синтетическая ссылка).warnings— что учесть:neural_off— векторный отбор не использован, кандидаты отобраны как вclassic; статус переранжировки сообщается отдельно; повторять запрос в другом режиме незачем;semantic_rerank_unavailable— переранжировка не выполнена из-за недоступных или некорректных данных/службы; причина вsemantic_rerank_reason;query_corrected— запрос исправлен, исходный — вcorrected_from;candidates_capped— дошли до конца пула кандидатов: дальше страниц нет, уточните запрос или фильтры.
Ошибки
| Код | Что значит и что делать |
|---|---|
| 400 | Неверный параметр — текст в error |
| 401 | Нет ключа или ключ отозван. Перебор ключей блокирует адрес на 30 минут |
| 402 | Не хватает денег. В теле — balance_rub, free_left_rub, price_rub: пополните баланс |
| 404 | Сайта нет в индексе (/v1/site) |
| 413 | Тело запроса больше 64 КБ |
| 429 | Превышен лимит скорости. Подождите столько секунд, сколько в заголовке Retry-After (то же число — в retry_after), и повторите |
| 501 | Параметр ещё не включён на сервере |
| 503 | Поиск временно недоступен — повторите через минуту |
Тело ошибки: {"error": "текст", "status": 429, "retry_after": 3}. В пачке queries ошибка одного запроса не отменяет остальные: у него в ответе поля error и status.
Лимиты
- Скорость — на ключ: бесплатный тариф — 1 запрос в секунду (всплеск до 5), платный — 10, бизнес — 50. Запросы пачки считаются по отдельности.
- Бесплатная выдача на сайте и
/api/search— для людей: до 10 поисков в минуту с адреса, без профилей сайтов. Для программ — только API с ключом.