
Ошибка 403 (403 Forbidden, «доступ запрещён») означает, что сервер получил и понял запрос, но отказывается его выполнять: у запрашивающего нет прав на этот файл, каталог или адрес. Сайт при этом работает. Причина — в правилах доступа на сервере: права файлов, запрет в .htaccess или nginx, блокировка по IP, стране или правилу WAF.
Ниже — отдельно, что делать посетителю, который увидел «403 Forbidden», и как владельцу сайта или разработчику API найти и убрать причину: по сообщениям в логах, заголовкам ответа и конфигурации сервера.
Что значит ошибка 403: код ответа HTTP 403 Forbidden
По RFC 9110 §15.5.4 код 403 означает, что сервер понимает запрос, но не авторизует его. Если в запросе были учётные данные (логин, токен, ключ API), сервер считает их недостаточными: повторять запрос с теми же данными бессмысленно, помочь могут только другие данные или изменение правил на сервере. Если учётных данных не было вовсе, а нужен вход, корректнее ответить 401 — но на практике многие сайты отдают 403 в обоих случаях.
Важная деталь из того же RFC: сервер, который не хочет раскрывать само существование закрытого ресурса, вправе вместо 403 ответить 404. Поэтому «страница не найдена» на приватном адресе — не всегда ошибка, иногда это та же 403, только замаскированная. Подробный разбор кода есть в справке MDN по коду 403.
Как выглядит код ошибки 403 для пользователя, зависит от сервера и защиты перед ним:
- Apache: «Forbidden. You don’t have permission to access this resource.»
- nginx: заголовок «403 Forbidden» и строка «nginx» под ним.
- Cloudflare: «Sorry, you have been blocked» или «Error 1020: Access denied» с идентификатором Ray ID.
- IIS: «403 — Forbidden: Access is denied», в логе — подстатус (например, 403.14 — просмотр каталога запрещён).
- Браузер или приложение: «HTTP ERROR 403», «Доступ запрещён», «Request failed with status code 403».
Если 403 показывает не браузер, а приложение — сервисы Apple и iMazing, Контур, магазины внутриигровых покупок, игровые лаунчеры, — это отказ серверов конкретного сервиса. Решается он через его поддержку или настройки аккаунта, а эта статья про сайты и API.
Чем 403 отличается от 401, 404 и других кодов
Коды 4xx похожи тем, что проблема на стороне запроса, но смысл у них разный. Путаница между ними приводит к неверной диагностике: 401 чинят входом, 404 — адресом, 403 — правами.
| Код | Что говорит сервер | Поможет ли вход или новый токен | Где искать причину |
|---|---|---|---|
| 401 Unauthorized | «Кто вы? Представьтесь»: учётных данных нет или они неверны | Да, для этого код и существует; ответ содержит заголовок WWW-Authenticate | Логин, токен, срок его жизни, заголовок Authorization |
| 403 Forbidden | «Знаю, кто вы, но сюда нельзя» или «сюда нельзя никому» | Только если у другого аккаунта или ключа есть нужные права | Права файлов, deny-правила, роли пользователя, WAF, IP- и гео-блокировки |
| 404 Not Found | «Такого ресурса нет» (или сервер скрывает, что он есть) | Нет | Адрес, маршрутизация, удалённые страницы |
| 429 Too Many Requests | «Слишком часто, подождите» | Нет, нужно снизить частоту; время ожидания — в Retry-After | Лимиты запросов |
| 451 Unavailable For Legal Reasons | «Закрыто по юридическим причинам» | Нет | Требования закона или правообладателя |
Подробнее о соседних кодах — в разборах ошибки 401 Unauthorized и ошибки 404 Not Found.
Ошибка 403 на сайте: что делать, если вы посетитель
Посетитель не может поменять права на чужом сервере, но может понять, закрыто ли всё для всех или только для него, и дать владельцу данные для разбора.
- Проверьте адрес. 403 часто возникает, когда адрес ведёт на каталог без файла (
/uploads/,/files/2024/) или на служебный путь. Уберите лишнюю часть адреса и откройте главную страницу. - Обновите страницу без кэша: Ctrl+F5 в Windows, Cmd+Shift+R в macOS. Браузер мог показать сохранённую ошибку.
- Удалите cookie этого сайта. Истёкшая сессия или устаревший CSRF-токен в форме нередко дают 403 при отправке формы. В Chrome: значок слева от адреса → «Настройки сайтов» → «Удалить данные».
- Войдите в аккаунт или проверьте роль. Страницы личного кабинета, админки и закрытых разделов отдают 403, если у вашей учётной записи нет доступа.
- Отключите расширения, которые меняют запросы (подмена User-Agent, удаление Referer). Защита от хотлинка отвечает 403 на картинки и файлы, если в запросе нет ожидаемого Referer.
- Проверьте, видят ли 403 другие. Откройте сайт с другого устройства или в другой сети либо проверьте ответ извне через проверку HTTP-заголовков enterno. Если извне приходит 200, а у вас 403 — заблокированы ваш IP, подсеть или регион.
Если заблокированы именно вы, напишите владельцу или в поддержку сайта. Приложите время ошибки, свой IP (его показывает определение IP), адрес страницы и, если это Cloudflare, Ray ID со страницы ошибки — по нему администратор найдёт событие за минуту. Блокировка по стране — решение владельца; снять её может только он.
Почему сервер выдаёт ошибку 403: частые причины
- Неправильные права файлов — 600 или 640 вместо 644, и веб-сервер не может прочитать файл.
- Нет права на «проход» по каталогу — у одного из каталогов на пути к файлу нет бита
xдля пользователя веб-сервера (например, домашний каталог с правами 700). - Владелец файла — не пользователь веб-сервера (root:root вместо www-data:www-data), а права закрыты для остальных.
- Отсутствует index-файл в директории, а просмотр каталога (directory listing) отключён.
- Блокировка в .htaccess или nginx —
Deny from all,Require all denied,deny all, слишком широкий шаблон вlocation. - ModSecurity или WAF-правило заблокировало запрос, похожий на атаку: SQL-фрагменты в параметрах, необычный User-Agent, большой POST.
- IP-блокировка через Cloudflare, fail2ban, firewall, плагин безопасности CMS или белый список IP для админки.
- Гео-блокировка — сервер или CDN закрывает доступ из отдельных стран.
- SELinux/AppArmor запрещает веб-серверу читать файл с чужим контекстом безопасности.
- Hotlink protection — Referer не соответствует разрешённым доменам.
- Права приложения — роль пользователя или ключ API не имеет доступа к ресурсу, CSRF-проверка не пройдена.
Сообщение в логе обычно прямо называет причину. Сводка самых частых строк:
| Строка в error.log | Сервер | Что означает | Что сделать |
|---|---|---|---|
open() "..." failed (13: Permission denied) | nginx | Нет прав на чтение файла или на проход по каталогу | Права 644/755, владелец, SELinux-контекст |
directory index of "..." is forbidden | nginx | В каталоге нет файла из директивы index, а autoindex выключен | Добавить index-файл или исправить index/try_files |
access forbidden by rule | nginx | Сработала директива deny | Найти правило: nginx -T | grep -n deny |
AH01630: client denied by server configuration | Apache 2.4 | Запрет Require в конфиге или .htaccess | Проверить Require и Deny для этого пути |
AH01276: Cannot serve directory ...: No matching DirectoryIndex | Apache | Нет index-файла, просмотр каталога запрещён Options -Indexes | Добавить index-файл или поправить DirectoryIndex |
AH00035: access to ... denied ... because search permissions are missing | Apache | У каталога на пути нет права x | chmod 755 на каталоги пути |
[id "949110"] Inbound Anomaly Score Exceeded | ModSecurity | Запрос набрал порог аномалий OWASP CRS | Найти правила, давшие баллы, и сделать точечное исключение |
Как проверить, кто отдаёт 403: сервер, WAF или CDN
Сначала важно понять, какой слой отвечает: ваш веб-сервер, приложение, WAF-модуль или CDN перед сайтом. От этого зависит, в каком логе искать.
- Проверьте ответ снаружи через HTTP Header Checker: он покажет код, цепочку редиректов и все заголовки.
server: cloudflareи заголовокcf-rayозначают, что ответ мог сформировать Cloudflare;cf-mitigated: challenge— что сработала проверка посетителя. - Прогоните Security Scanner — он покажет, не выдают ли заголовки версию сервера и модулей, и какие защитные заголовки настроены.
- Сравните ответы для разных клиентов из консоли.
# Linux / macOS: только заголовки ответа
curl -sI https://example.com/page
# Тот же запрос с браузерным User-Agent: если код изменился, блокирует WAF по User-Agent
curl -sI -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" https://example.com/page
# Обход CDN для диагностики своего сервера: запрос прямо на IP origin
curl -sI --resolve example.com:443:203.0.113.10 https://example.com/page
# Windows PowerShell: вызывайте именно curl.exe, а не псевдоним Invoke-WebRequest
curl.exe -sI https://example.com/pageЕсли запрос напрямую на origin возвращает 200, а через домен — 403, блокирует CDN или WAF перед сервером. Если 403 и напрямую — ищите причину в логах своего сервера:
# nginx
tail -50 /var/log/nginx/error.log | grep -i "forbidden\|403\|denied"
# Apache
tail -50 /var/log/apache2/error.log
tail -50 /var/log/apache2/access.log | grep " 403 "
# ModSecurity
tail -50 /var/log/modsec_audit.log
# Проверка прав
ls -la /var/www/html/problem-file
# Должно быть: -rw-r--r-- 1 www-data www-data
# Права на каждый каталог по пути к файлу
namei -l /var/www/html/problem-fileГде лежат логи и как настроить их формат, чтобы в access.log попадал нужный контекст, — в статье логи nginx. В CentOS и RHEL логи Apache лежат в /var/log/httpd/, а не в /var/log/apache2/.
Как исправить ошибку 403 на своём сервере
Решения идут в том порядке, в котором причины встречаются чаще всего.
1. Исправить права файлов и владельца
# Файлы
find /var/www/html -type f -exec chmod 644 {} \;
# Директории
find /var/www/html -type d -exec chmod 755 {} \;
# Владелец
chown -R www-data:www-data /var/www/htmlПользователь веб-сервера зависит от дистрибутива: www-data в Debian и Ubuntu, apache или nginx в CentOS, Rocky и AlmaLinux. Посмотреть его можно командой ps -eo user,comm | grep -E "nginx|apache|httpd|php-fpm". Файлы с секретами (wp-config.php, .env) можно оставить 640 или 600 — важно лишь, чтобы их читал пользователь PHP-FPM.
2. Проверить index-файл
# nginx
index index.php index.html;
# Apache
DirectoryIndex index.php index.htmlВ nginx 403 на каталог даёт и типичная строка try_files $uri $uri/ =404;: если каталог существует, а index-файла в нём нет, nginx отвечает 403. Для SPA и фронт-контроллеров нужна другая форма: try_files $uri $uri/ /index.php?$args; или /index.html. Включать autoindex on ради устранения 403 не стоит — это откроет список файлов всем.
3. Найти блокировку в .htaccess
# Ищите:
Deny from all
Require all denied
# Замените на:
Require all grantedОткрывайте доступ только к тому, что действительно должно быть публичным: запрет на .env, .git и служебные каталоги должен остаться. Не смешивайте синтаксис Apache 2.2 (Order/Deny) и 2.4 (Require) в одном блоке — результат трудно предсказать. Найти все правила быстро поможет grep -rn -E "Deny|Require|Order" /var/www/html --include=.htaccess. Подробнее — в разборе файла .htaccess и в документации Apache по управлению доступом.
4. nginx: deny-директивы
# Проблемная строка:
location ~ \.(env|git|htaccess)$ {
deny all;
}
# Если блокировка слишком широкая — пересмотрите паттернВесь итоговый конфиг со всеми include выводит nginx -T. Директивы allow и deny проверяются по порядку до первого совпадения, поэтому deny all; выше allow закроет доступ всем. Синтаксис описан в документации модуля ngx_http_access_module. После правки — nginx -t && systemctl reload nginx.
5. Ошибка 403 только по HTTPS
Если по http:// страница открывается, а по https:// отдаёт 403, у блока для порта 443 свои root, allow/deny или правила доступа. Сравните блоки:
# nginx: все listen, root и deny с номерами строк
nginx -T 2>/dev/null | grep -n -E "listen|server_name|root|deny|allow"
# Apache: какие виртуальные хосты обслуживают 80 и 443
apachectl -S6. ModSecurity: ложное срабатывание
# Определите правило в логе:
# [id "949110"] [msg "Inbound Anomaly Score Exceeded"]
# Отключите конкретное правило для URL
SecRule REQUEST_URI "@beginsWith /api/safe-endpoint" \
"id:1001,phase:1,ctl:ruleRemoveById=949110,nolog,allow"Правило 949110 — итоговое: оно только суммирует баллы. Точнее отключать те правила, что начислили баллы (их id стоят в том же аудит-логе выше), и только для конкретного пути или параметра. Отключение ModSecurity целиком ради одной формы оставит сайт без защиты.
7. Проверить IP-блокировки
# fail2ban
fail2ban-client status
fail2ban-client status sshd
fail2ban-client set sshd unbanip 198.51.100.7
# iptables
iptables -L -n | grep DROP
iptables -D INPUT -s 198.51.100.7 -j DROP
# nftables
nft list ruleset | grep -n 198.51.100.7Заблокированный через firewall IP обычно получает таймаут, а не 403. Ответ 403 приходит, когда запрет стоит в веб-сервере (deny, Require not ip), в плагине безопасности CMS или в WAF.
8. SELinux и AppArmor (CentOS/RHEL, Ubuntu)
ls -Z /var/www/html/
# Должно быть httpd_sys_content_t
restorecon -Rv /var/www/html/
chcon -t httpd_sys_content_t /var/www/html/newfile.php
# Недавние отказы SELinux
ausearch -m avc -ts recentТипичный случай — файлы перенесли командой mv из домашнего каталога: они сохраняют контекст исходного места, и права 644 не помогают, пока не выполнить restorecon. В Ubuntu аналогичные отказы AppArmor видно в journalctl -k | grep -i apparmor.
9. PHP-FPM: «Access denied.»
Если вместо страницы приходит 403 с текстом «Access denied.», PHP-FPM отказался исполнять файл, расширение которого не входит в security.limit_extensions (по умолчанию только .php). Обычно это значит, что в nginx на PHP-FPM отправляются не только PHP-файлы — проверьте location ~ \.php$, а не расширяйте список.
10. WordPress
- Переименуйте
.htaccess, зайдите в Настройки → Постоянные ссылки для регенерации. - Проверьте плагины безопасности (Wordfence, iThemes) — могли заблокировать IP.
chmod 644 wp-config.php,chmod 755 wp-content/- Если админка недоступна, временно отключите все плагины, переименовав каталог
wp-content/pluginsпо SFTP, и включайте их по одному.
«Forbidden. You don’t have permission to access this resource» в Apache
Эту страницу выдаёт Apache 2.4; в старых версиях текст звучал как «You don’t have permission to access / on this server». Сама фраза причину не называет — она всегда есть в error.log рядом с IP клиента. Три сообщения покрывают почти все случаи:
AH01630: client denied by server configuration— сработалRequire all deniedилиDeny from all. Частая причина после переезда на Apache 2.4 — блок<Directory>для нового DocumentRoot безRequire all granted.AH01276— в каталоге нет index-файла, аOptions -Indexesзапрещает листинг.AH00035 ... search permissions are missing— у каталога на пути нет битаx.
Минимальный корректный блок для каталога сайта в Apache 2.4:
<Directory /var/www/html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>После правки — apachectl configtest и systemctl reload apache2 (в CentOS — httpd).
403 от Cloudflare и WAF
Если в ответе есть cf-ray, а в логах вашего сервера этого запроса нет вовсе, запрос остановил Cloudflare. Страница «Sorry, you have been blocked» означает срабатывание правила WAF или управляемых правил, «Error 1020» — пользовательского правила доступа. Что делать:
- Возьмите Ray ID со страницы ошибки или из заголовка
cf-ray. - В панели Cloudflare откройте раздел Security → Events и найдите событие по Ray ID или IP: там указано, какое правило сработало и почему.
- Сузьте правило или добавьте исключение для конкретного пути, IP партнёра или верифицированных ботов, а не отключайте защиту целиком.
Разбор кода 1020 — в статье Cloudflare Error 1020 Access Denied. Для других WAF (Qrator, DDoS-Guard, облачные WAF хостингов) логика та же: идентификатор запроса на странице блокировки → журнал событий WAF → точечное исключение.
Ошибка 403 из-за блокировки по стране или IP
Гео-блокировка — сознательное решение владельца: закрыть сайт для стран, откуда идут атаки или спам, или ограничить доступ к админке. Проблемы начинаются, когда правило задевает своих: базы GeoIP ошибаются для мобильных операторов и адресов облачных провайдеров, а корпоративный NAT выводит сотни сотрудников через один IP, который мог попасть под автоматический бан.
Пример гео-ограничения в nginx с модулем GeoIP2 — ответ 403 только тем, кого вы решили закрыть:
# http-контекст: переменная $geoip2_data_country_code задаётся модулем geoip2
map $geoip2_data_country_code $allowed_country {
default yes;
XX no; # код страны, которую нужно закрыть
}
# server-контекст
if ($allowed_country = no) {
return 403;
}Если на такие правила жалуются посетители, проверьте актуальность базы GeoIP, добавьте белый список для партнёров и не распространяйте блокировку на поисковых роботов, если сайт должен индексироваться. Для посетителей в закрытых регионах полезно отдавать страницу с объяснением и контактом, а не голое «403 Forbidden».
Request failed with status code 403: ошибка 403 в API, axios и requests
В API код 403 почти всегда означает «аутентификация прошла, авторизация — нет». Клиентские библиотеки показывают его по-разному: axios бросает AxiosError: Request failed with status code 403, Python requests после raise_for_status() — 403 Client Error: Forbidden for url, а fetch исключения не бросает вовсе, и 403 видно только в response.status.
Главное правило — читать тело ответа: сервер почти всегда объясняет причину там.
// axios
try {
await axios.get('https://api.example.com/v1/items', {
headers: { Authorization: `Bearer ${token}` },
});
} catch (err) {
if (err.response?.status === 403) {
console.log(err.response.headers);
console.log(err.response.data); // здесь причина: scope, IP, план
}
}# Python requests
import requests
r = requests.get(
"https://api.example.com/v1/items",
headers={"Authorization": f"Bearer {token}", "User-Agent": "my-app/1.0 (admin@example.com)"},
timeout=10,
)
print(r.status_code, r.headers.get("Content-Type"))
print(r.text[:500]) # сообщение сервера о причине отказаЧастые причины ошибки 403 в API:
- У ключа или токена нет нужного scope или роли — ключ «только на чтение» при запросе на запись, токен другого проекта или окружения (тестового вместо боевого).
- IP не в белом списке ключа — запросы с нового сервера или из CI.
- CSRF: Django отвечает 403 «CSRF verification failed. Request aborted.», если POST из браузера пришёл без токена или с чужого Origin.
- WAF перед API режет клиента по User-Agent: заголовок по умолчанию
python-requests/2.xили пустой User-Agent многие фильтры считают ботом. Для своего API добавьте клиента в исключения; для чужого — используйте официальный API и ключ, а не маскировку под браузер. - Подписанная ссылка истекла: хранилища вроде Amazon S3 отвечают на просроченную presigned-ссылку 403 AccessDenied.
- Лимиты: часть API (например, GitHub) при превышении лимита отвечает 403, а не 429 — отличить можно по тексту ответа и заголовкам лимитов.
- Preflight CORS: если сервер отвечает 403 на запрос
OPTIONS, браузер покажет ошибку CORS, хотя корень проблемы — правило доступа, не пропускающее OPTIONS без авторизации.
403 на /admin или /wp-admin — что делать
Если сайт работает, но админка отдаёт 403:
- Проверьте IP allowlist в
.htaccessили nginx — у вас мог смениться внешний IP. - Проверьте Cloudflare Firewall Rules на admin path.
- Посмотрите fail2ban — возможно, ваш IP заблокирован после неудачных входов.
- Уточните 2FA — некоторые плагины возвращают 403 при неверном TOTP.
- Проверьте HTTP Basic Auth перед админкой: при неверном пароле он отдаёт 401, но конфликт
auth_basicиdenyв одном location может давать 403.
Как не пропустить 403 в будущем
403 — это диалог о правах доступа. Начинайте с логов, проверяйте права файлов и владельца, ищите deny-правила в .htaccess и nginx, исключайте WAF и IP-блокировки. Самые неприятные 403 появляются после выкладки, переноса файлов или обновления правил WAF и замечаются, когда пользователи уже ушли. Настройте мониторинг на expected_code=200 для главной, страниц оплаты и ключевых точек API, чтобы отлавливать 403-регрессии сразу.
Частые вопросы
В чём разница между 401 и 403?
401 — «авторизуйся»: учётных данных нет или они неверны, и вход может помочь. 403 — «у тебя нет доступа»: сервер знает, кто вы, но прав недостаточно, либо ресурс закрыт для всех.
Почему после scp файл отдаёт 403?
Файл получает владельца и права того, кто его копировал, — часто root и 600. Сделайте chown www-data:www-data file && chmod 644 file, а в CentOS/RHEL ещё restorecon -v file.
Как отличить 403 от сервера и от WAF?
Посмотрите заголовки Server: и cf-ray: Cloudflare обычно показывает свою страницу с Ray ID, и запроса нет в логах вашего сервера. Enterno.io HTTP Checker покажет все заголовки ответа.
403 у Googlebot или Яндекс-робота — это плохо?
Критично: закрытые страницы выпадают из индекса. Проверьте WAF, гео-правила и плагины безопасности. Настоящего робота подтверждают обратным DNS: host 66.249.66.1 должен вернуть имя в googlebot.com или google.com, для Яндекса — в yandex.ru, yandex.net или yandex.com, и прямой запрос этого имени должен вернуть тот же IP.
Можно ли вместо 403 отдавать 404?
Да, RFC 9110 это разрешает, если нужно скрыть само существование ресурса — так поступают с приватными репозиториями и служебными путями. Для страниц, которые пользователь должен видеть после входа, честнее 403 или редирект на вход.
Почему ошибка 403 появляется не всегда, а время от времени?
Так ведут себя динамические блокировки: лимиты запросов, fail2ban, антибот-проверки WAF. Ищите закономерность по времени и IP в access.log и журнале событий WAF.