Что такое CORS — и почему ошибка в консоли это защита, а не баг

Ты собрал фронтенд, он дёргает твой же API, и в консоли — красное: blocked by CORS policy. Первая мысль: «сервер лежит». Вот сюрприз: сервер жив, запрос дошёл, ответ пришёл. Просто браузер посмотрел на этот ответ и решил не отдавать его твоему коду.
Звучит абсурдно — сервер ответил, а ты ответа не видишь? Но в этом и есть весь смысл CORS. Это не поломка. Это браузер защищает пользователя. Разберёмся, от чего именно — и почему чинить надо не там, где красное.
Что такое CORS простыми словами
CORS расшифровывается как Cross-Origin Resource Sharing — «обмен ресурсами между разными источниками».
«Источник» (origin) — это связка из трёх вещей: протокол + домен + порт. https://myapp.com и https://api.myapp.com — это разные источники (домен отличается). http://localhost:3000 и http://localhost:8000 — тоже разные (порт отличается).
По умолчанию у браузера есть строгое правило: код с одного источника не может свободно читать ответы с другого. Это называется Same-Origin Policy. CORS — это механизм, которым сервер говорит браузеру: «вот этому источнику читать мои ответы можно, я разрешаю».
Аналогия: два соседних двора и охранник между ними. По умолчанию он не пускает чужих. Но хозяин второго двора может оставить список: «жильцов из дома напротив пропускать». CORS — это и есть тот список разрешённых.
Кого на самом деле защищает CORS
Тут главная путаница новичков. CORS защищает не твой сервер. Он защищает пользователя в браузере.
Представь: ты залогинен в своём банке в одной вкладке. В другой открываешь безобидный с виду сайт. Без Same-Origin Policy скрипт на том сайте мог бы тихо сделать запрос к банку от твоего имени (твои куки же на месте) и прочитать ответ — баланс, переводы. Same-Origin Policy это запрещает: чужой источник не прочитает ответ банка.
То есть CORS — это правило браузера про чтение ответов, а не замок на сервере. Сервер по-прежнему обязан сам проверять, кто к нему стучится. Поэтому важно понять: CORS не делает твой API безопасным — он лишь не даёт чужим страницам читать ответы за спиной пользователя.
Почему ты видишь ошибку
Теперь понятно, почему ошибка такая странная. Когда твой фронт с одного источника зовёт API на другом, браузер пропускает запрос, сервер его обрабатывает и отвечает. Но прежде чем отдать ответ твоему JavaScript, браузер проверяет: есть ли в ответе разрешающий заголовок Access-Control-Allow-Origin с твоим источником?
Нет заголовка — браузер выбрасывает ответ и пишет в консоль ошибку CORS. Запрос состоялся, ты просто не получил результат.
Часто перед «настоящим» запросом браузер шлёт ещё и предварительный (preflight) — короткий запрос методом OPTIONS: «эй, сервер, мне вообще можно к тебе с этого источника таким методом?». Если сервер не ответил правильными заголовками на этот OPTIONS, основной запрос даже не уйдёт.
Как это починить
Раз решает заголовок в ответе, чинить надо на сервере, а не во фронтенде. Никакие пляски в браузере (отключить, обойти) — это не починка, а самообман.
- Найди, кто отдаёт ответ — твой бэкенд, edge-функция, прокси.
- Добавь в ответ заголовок
Access-Control-Allow-Originсо своим источником, напримерhttps://myapp.com. На время локальной отладки можноhttp://localhost:3000. - Обработай preflight — сервер должен отвечать на запрос
OPTIONSтеми же разрешающими заголовками, иначе основной запрос не пройдёт. - Не ставь
*в продакшене. Звёздочка разрешает читать ответы кому угодно. Для публичного открытого API это нормально, для приватного — перечисляй конкретные источники.
В готовых фреймворках это одна-две строки или плагин (cors в Express, настройка в Supabase Edge Functions). Если фронт и API живут на одном источнике — например, через общий деплой с прокси — проблема CORS вообще не возникает. Подробнее про сам процесс обращения к чужому серверу — в гайде как подключить API.
Частые вопросы
Можно ли отключить CORS в браузере и не мучиться?
Только для своей локальной отладки (есть флаги и расширения) — и это плохая привычка. У твоих пользователей CORS остаётся включён всегда, отключить его у них ты не можешь. Если «работает только с выключенным CORS», значит починка не сделана. Чини заголовки на сервере.
CORS защищает мой сервер от взлома?
Нет. CORS — правило браузера про чтение ответов, оно не мешает кому угодно слать запросы к твоему API напрямую (например, из скрипта вне браузера). Безопасность API — это отдельно: авторизация, проверка токена, лимиты. CORS просто закрывает один конкретный сценарий — кражу ответов через чужую вкладку.
Почему всё работает в Postman, но падает в браузере?
Потому что CORS — это браузерное правило. Postman, curl и серверный код не браузеры, Same-Origin Policy на них не распространяется — они получают ответ как есть. Так что «в Postman ок» не значит, что CORS настроен; это значит, что ты проверял в обход того, кто его применяет.
Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.





