Сервер получил запрос, но строку из заголовка x-api-key (в OpenAI-совместимом формате это Authorization: Bearer) не смог сопоставить ни с одним действующим ключом. Так выглядит «Invalid API key». Anthropic отвечает на это HTTP 401 с типом authentication_error, и это не ошибка в теле запроса. Модель и промпт тут ни при чём: сломались учётные данные, которые дошли до сервера. Причин четыре, и ни одну не нужно выяснять через поддержку.
Как выглядит ошибка
Сырой ответ сервера:
{
"type": "error",
"error": {
"type": "authentication_error",
"message": "invalid x-api-key"
}
}
Что вы увидите, зависит от инструмента:
- curl печатает этот JSON целиком, код ответа
401. - Python и Node SDK заворачивают его в исключение аутентификации (в Python это
anthropic.AuthenticationError), а то же сообщение попадает в трейсбек. - Claude Code показывает ошибку в терминале при первом обращении к модели. CLI передаёт ответ API как есть, в лучшем случае добавляя подсказку проверить переменные окружения.
- Cursor и другие IDE с пользовательским API-ключом ругаются на первом тестовом запросе после сохранения ключа, обычно статусом
authentication errorв настройках подключения.
Везде одна и та же строка: invalid x-api-key. Причины ниже идут от самой частой к самой редкой.
Причина 1: опечатка в ключе или он отозван
Самая обыденная. Ключ Anthropic выглядит как sk-ant-api03-... и показывается один раз, при создании. Скопировали не до конца или зацепили лишний символ, и сервер получил строку, не похожую ни на один ключ. Ответ будет тот же, что на случайный набор букв.
Отозванный ключ неотличим от неверного: текст ошибки совпадает. Ключи отзывают вручную из консоли, а у ключей с заданным сроком действия отзыв происходит сам, когда срок вышел. Проверить просто: откройте в консоли список ключей и посмотрите, есть ли там нужный и активен ли он. Если его нет, выпускайте новый. Старое значение восстановить нельзя.
Причина 2: ключ из другой организации
Про неё забывают чаще всего, потому что ключ выглядит исправным: он существует, не просрочен, скопирован без ошибок. Но личный ключ Anthropic привязан к организации в консоли. Если вас из неё удалили или вы вышли сами, ключ перестаёт проходить аутентификацию. Так же бывает, когда организаций несколько (скажем, личная и рабочая): ключ создан в одной, а вы рассчитываете на настройки другой. Лимиты, модели и биллинг у них свои, и ключ чужие настройки не подхватит.
Есть и частный случай. Если ключ работает сразу в нескольких рабочих пространствах (workspaces), в запрос может понадобиться заголовок с идентификатором рабочего пространства. Без него сервер порой не понимает, к какому пространству отнести запрос, и отвечает той же ошибкой. Администраторам организаций с несколькими пространствами стоит проверить это сразу после самого ключа.
Причина 3: пробел или перенос строки в переменной окружения
Из консоли ключ копируется одним движением, но до переменной окружения ему есть где испортиться:
- терминал при вставке дописывает в конец перенос строки;
- в
.envпосле знака равенства остался пробел; - ключ скопирован из документа или чата, где текст переносился, и в середину строки попал невидимый перенос.
Глазами ничего не заметно, а сервер сравнивает ключ посимвольно, и один лишний байт рушит совпадение. Проверка в терминале:
echo -n "$ANTHROPIC_API_KEY" | wc -c
echo -n "$ANTHROPIC_API_KEY" | cat -A | tail -c 20
Первая команда выводит длину значения. Если она больше ожидаемой на один-два символа, где-то сидит лишний пробел или \n; в выводе cat -A его выдаст $ в неожиданном месте. Надёжнее другой путь: удалить переменную и задать заново, набрав export руками, а ключ вставить без кавычек по краям.
Причина 4: ключ не от того адреса сервера
Ключ Anthropic sk-ant-... и ключ codexkey sk_cdx_... рассчитаны на разные базовые адреса. Отправите sk_cdx_... на api.anthropic.com, и Anthropic не узнает в нём свой формат: придёт authentication_error. Наоборот тоже не сработает: sk-ant-..., посланный на https://api.codexkey.ru, шлюз отклонит, потому что ждёт ключ своего формата.
Путаница возникает при переезде с одного сервиса на другой. base_url поменяли в одном месте конфигурации, а прежний ключ остался в переменной окружения или в настройках IDE, или наоборот. Поэтому проверяйте пару «ключ и адрес» целиком.
Как быстро найти причину
Порядок, который закрывает все четыре случая за пару минут:
- Посмотрите первые 10-12 символов ключа:
sk-ant-значит Anthropic,sk_cdx_значит codexkey. Сверьте сbase_url, на который он уходит. - Измерьте длину значения в переменной окружения командой выше, чтобы исключить пробел или перенос строки.
- Откройте список ключей (в консоли Anthropic или в личном кабинете codexkey) и убедитесь, что ключ там есть, активен и создан в нужной организации или рабочем пространстве.
- Если всё сходится, а ошибка осталась, выпустите новый ключ и замените старый. Иногда это быстрее, чем искать, где именно испортилось прежнее значение.
Если дело в самом ключе Anthropic
Проверка показала, что опечаток и проблем с окружением нет: ключ Anthropic отозван, организация закрыла доступ, или вы просто не хотите зависеть от одного ключа. В этом случае к моделям Claude можно подключиться через отдельный ключ codexkey, никак не связанный с прежним аккаунтом.
Ключ создаётся в личном кабинете, в разделе «API-ключи», и выглядит как sk_cdx_.... Для прямых вызовов API и SDK базовый адрес такой: https://api.codexkey.ru.
import anthropic
client = anthropic.Anthropic(
api_key="sk_cdx_ВАШ_КЛЮЧ",
base_url="https://api.codexkey.ru",
)
message = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Привет"}],
)
print(message.content[0].text)
Claude Code настраивается двумя переменными окружения, входить в консоль Anthropic для этого не нужно. Шаги для Linux, macOS и Windows расписаны в статье «Claude Code в России». Остальные коды ошибок API (429, 500, 529) собраны в гиде по ошибкам Claude API. Актуальные модели и цены смотрите на странице моделей, а завести ключ и оформить доступ к API можно на странице «Купить Claude API».
FAQ
Почему curl возвращает «invalid x-api-key», если ключ скопирован правильно?
Чаще всего виноваты невидимые символы: перенос строки в конце значения или пробел после знака равенства в .env. Измерьте длину командой echo -n "$ANTHROPIC_API_KEY" | wc -c и сравните с ожидаемой длиной ключа.
Может ли ключ перестать работать сам, без моих действий?
Да. Личный ключ Anthropic привязан к организации в консоли и перестаёт проходить аутентификацию, если вас из неё удалили. Ключи со сроком действия истекают автоматически, по расписанию, заданному при создании.
Чем 401 отличается от 403, если обе ошибки про доступ?
401 authentication_error означает, что сам ключ не признан действительным. 403 permission_error означает, что ключ рабочий, но прав на конкретный ресурс или модель у него нет: например, модель отключена для вашего тарифа или ключ ограничен списком разрешённых моделей.
Можно ли использовать ключ codexkey вместо ключа Anthropic и наоборот?
Нет. Форматы разные (sk_cdx_... против sk-ant-...), и каждый ключ работает только со своим базовым адресом: ключ codexkey с https://api.codexkey.ru, ключ Anthropic с api.anthropic.com. При переходе в коде обычно достаточно заменить одну строку, base_url.
Надо ли менять заголовок запроса при переходе на codexkey?
Нет, если вы работаете через Anthropic SDK или совместимый формат: заголовок остаётся x-api-key, меняются только значение ключа и base_url. В OpenAI-совместимом формате заголовок Authorization: Bearer, и правило то же.
Ошибка появилась внезапно, а вчера всё работало. Что изменилось?
Начните с консоли ключей: ключ могли отозвать вручную, у него мог закончиться срок действия, или поменялся состав организации. Если с ключом всё в порядке, а со вчерашнего дня менялось окружение (переустановка зависимостей, правка .env, другой терминал), подозревайте лишний символ, попавший в переменную при копировании.