Ошибка 403 у ElevenLabs в России: мы проверили с московского сервера, и это не 403
Все пишут, что ElevenLabs отдаёт 403 Forbidden на российских IP. Мы замерили с сервера в Москве 3 августа 2026: на самом деле приходит редирект 302 на страницу справки. Разбираем, почему это важно и почему из-за этого виджет молчит без ошибки.
Если загуглить «elevenlabs 403», выдача уверенно расскажет, что сервис отдаёт 403 Forbidden российским пользователям. Мы решили проверить руками, а не по пересказам: взяли сервер в Москве и сервер в Роттердаме и отправили одинаковые запросы к API ElevenLabs.
403 там нет. С российского адреса ElevenLabs отвечает 302 Found и редиректит на собственную статью справки про ограниченные страны. Разница выглядит мелочью, но именно она объясняет, почему голосовой виджет на сайте молчит вместо того, чтобы показать ошибку.
Что именно мы замерили
Дата замера: 3 августа 2026. Две точки: сервер в Москве (российский хостинг, обычный адрес) и сервер в Роттердаме (европейский адрес без пометок). Запросы одинаковые, curl, без авторизации.
| Запрос | Из Роттердама | Из Москвы |
|---|---|---|
| GET /v1/models | JSON, content-type: application/json | 302 на страницу справки, text/html |
| GET /v1/convai/conversation/get-signed-url | 401, JSON с описанием ошибки | 302 на страницу справки |
| GET /v1/convai/agents/{id} | JSON | 302 на страницу справки |
| WebSocket-хендшейк /v1/convai/conversation | обрабатывается, JSON-ответ | 302 на страницу справки |
| https://elevenlabs.io/ | 200 | 302 на страницу справки |
| Скрипт виджета с unpkg.com | 200 | 200, грузится нормально |
Заголовки ответа из Москвы:
HTTP/2 302
location: https://help.elevenlabs.io/hc/en-us/articles/22497891312401-...
content-type: text/html; charset=UTF-8
content-length: 338
Куда ведёт редирект: на официальную справку ElevenLabs «Do you restrict access to the service and platform for any specific countries», где перечислены Беларусь, Куба, Иран, Северная Корея, Россия, Сирия, Крым, Донецкая и Луганская области.
Почему 302 хуже, чем 403
Казалось бы, разница чисто косметическая. На практике она принципиальная, и вот почему.
403 это честный отказ. Клиентский код видит статус 4xx, понимает, что запрос отклонён, и может это обработать: показать сообщение, залогировать, отвалиться с ошибкой.
302 это указание «иди в другое место». Браузер и большинство HTTP-клиентов следуют за редиректом молча и автоматически. Код, отправивший запрос, получает в итоге 200 OK и тело ответа. Только тело это не JSON с данными агента, а HTML-страница справочного центра.
Дальше происходит вот что. Код виджета ждёт JSON, получает HTML, парсинг падает. А поскольку сценарий «сервер вернул страницу помощи вместо данных» разработчиками виджета не предусмотрен, обработчика для него нет. Исключение уходит в никуда.
Отсюда симптом, который все описывают одинаково: кнопка есть, диалог не поднимается, ошибки нет.
Почему всё выглядит целым
Отдельная деталь из замера: скрипт самого виджета (@elevenlabs/convai-widget-embed) отдаётся с unpkg.com и из России загружается совершенно нормально, статус 200. Это обычный npm-CDN, к ElevenLabs он отношения не имеет и никого не блокирует.
Получается идеальная маскировка сбоя:
- Страница грузится полностью.
- Скрипт виджета скачивается и выполняется.
- Кнопка агента отрисовывается в углу экрана, всё как задумано.
- Посетитель нажимает.
- Виджет идёт к
api.elevenlabs.io, получает редирект на справку, тихо ломается. - Ничего не происходит. Совсем ничего.
В консоли браузера при этом что-то будет: неудачный WebSocket, ошибка парсинга. Но в консоль посетитель не смотрит, а владелец сайта не смотрит тем более, потому что у него всё работает (он под VPN, и это отдельная история).
Четыре разные причины, которые все зовут «403»
Раз уж мы разбираем ошибки, полезно развести случаи, которые в форумных тредах свалены в одну кучу. Симптомы похожи, причины разные, лечатся по-разному.
1. Гео-ограничение по санкциям. То самое, что мы замерили: 302 на справочную страницу, приходит на любой запрос с российского адреса, включая простое открытие elevenlabs.io в браузере. Ключевой признак: срабатывает до всякой авторизации, ключ API не нужен, тело ответа это HTML, а не JSON.
2. Флаг за подозрительную активность на бесплатном тарифе. Здесь ответ приходит уже нормальный, JSON, и в нём фигурирует необычная активность. Причина чаще всего в общем выходном IP: вы зашли через VPN, чей адрес делите с чужим аккаунтом. В справке ElevenLabs про это сказано прямо, и там же сказано, что снять флаг они не могут. Признак: аккаунт бесплатный, ответ в формате JSON, проблема появилась после входа под туннелем.
3. Проблема с ключом. Неверный, отозванный или не переданный ключ даёт 401 с внятным JSON. Мы это тоже увидели в замере: запрос без ключа из Роттердама вернул 401 и сообщение «Neither authorization header nor xi-api-key received». Признак: статус 401, а не 403 и не 302, и в теле прямо написано про авторизацию.
4. Исчерпанная квота или ограничение тарифа. Тоже приходит с внятным JSON и описанием, какой лимит упёрся. Признак: работало и перестало примерно в тот момент, когда кончились символы или минуты.
Как отличать на практике. Откройте DevTools, вкладку Network, и посмотрите на сам ответ. Три вопроса по порядку: какой статус, какой content-type, есть ли редирект. Если content-type: text/html и в location стоит адрес справочного центра, это первый случай, гео. Всё остальное придёт как JSON и объяснит себя словами.
Что с этим можно сделать
Если вы упёрлись в первый случай, вариантов ровно два: сменить адрес, с которого идёт запрос, либо пустить запрос через посредника с подходящим адресом.
Для личного использования это VPN, но с оговоркой: выходной адрес не должен быть помечен как российский. Многие массовые сервисы этот тест не проходят, потому что их диапазоны давно переехали в RU по гео-базам.
Для виджета на сайте VPN не подходит в принципе. Виджет выполняется в браузере посетителя, и вы не можете попросить каждого поставить туннель ради разговора с ботом. Здесь нужен релей: узел с чистым адресом, через который проходит трафик виджета. Можно собрать самому, можно взять готовый.
ElevenProxy это ровно второе: в разметке меняется одна строка, дальше запросы виджета идут через наш узел, посетитель ничего не устанавливает. Проверить свой виджет можно бесплатно и без регистрации, чекер как раз показывает, приходит ли редирект с российского узла.
Проверьте у себя
Скрипт, которым сделан этот замер, выложен открыто: github.com/vadimsky-ctrl/elevenlabs-ru-check. Без зависимостей, только стандартная библиотека Python.
python3 elevenlabs-check.py
Он проверяет четыре пути (REST, подпись сессии ConvAI, сайт, WebSocket-хендшейк), не следует за редиректом и говорит, что именно пришло. Там же в measurements/ лежат сырые JSON-выводы обеих точек этого замера, так что результаты можно сверить, а не принимать на веру.
Оговорка про методику
Замер сделан 3 августа 2026 с одного московского адреса и одного европейского. Одна точка это не статистика: не исключено, что для части российских диапазонов поведение отличается, а сам механизм ElevenLabs может поменять в любой момент, не предупреждая. Если у вас получилось иначе, напишите на hello@elevenproxy.ru, перепроверим и обновим статью.
Что здесь точно не поменяется, так это причина: ElevenLabs закрывает Россию по санкционному законодательству США, а не по требованию Роскомнадзора. В реестре РКН сервиса нет, блокирует его собственный владелец.
Узнайте, режется ли ваш агент ElevenLabs по гео для РФ — и почините заменой одной строки.