Перейти к содержимому
SEO/Опубликовано 20 октября 2026 г./5 мин

ERR_CLEARTEXT_NOT_PERMITTED: приложение запрещает HTTP

ERR_CLEARTEXT_NOT_PERMITTED — Android запретил приложению открыть адрес по http без шифрования. Прогнали код Android 16 и 17 на 11 вариантах network_security_config и показали, какие правила работают, а какие молча не действуют.

ERR_CLEARTEXT_NOT_PERMITTED: приложение запрещает HTTP
N
Команда NEXFORCE
Кто пишет блог

net::ERR_CLEARTEXT_NOT_PERMITTED — ошибка Android-приложения: оно попыталось открыть адрес по http без шифрования, а сетевая политика приложения такой трафик запрещает. Чаще всего её видно на экране WebView — встроенного браузера, через который приложения показывают веб-страницы. Сайт при этом может работать: в обычном браузере он откроется.

Мы разобрали исходный код Android, Chromium и OkHttp и прогнали настоящий системный код Android 16 и 17 на 11 вариантах файла network_security_config и 14 адресах.

Короткий ответ

Причина почти всегда одна из трёх:

  1. Приложение собрано с targetSdkVersion 28 или выше, а адрес начинается с http://. С Android 9 такой трафик по умолчанию запрещён.
  2. В манифесте есть network_security_config, и для нужного хоста в нём нет cleartextTrafficPermitted="true". Атрибут android:usesCleartextTraffic в этом случае не действует.
  3. Правило в файле написано так, что ни с чем не совпадает: звёздочка, диапазон адресов, адрес со схемой http://. Система такие записи принимает без ошибки.

Правильное исправление — перевести адрес на https. Разрешать HTTP стоит только для конкретных хостов, которые без него не работают.

Что означает ошибка

В Chromium ошибка описана в файле net/base/net_error_list.h:

// The request was blocked by system policy disallowing some or all cleartext
// requests. Used for NetworkSecurityPolicy on Android.
NET_ERROR(CLEARTEXT_NOT_PERMITTED, -29)

Запрос заблокирован системной политикой, которая запрещает часть или все незашифрованные запросы. Политика — это NetworkSecurityPolicy Android. В справке Android под cleartext понимается любой трафик без TLS: HTTP, FTP, а в описании NetworkSecurityPolicy перечислены ещё XMPP, IMAP и SMTP без шифрования.

Одна и та же проверка выглядит по-разному в зависимости от того, какая библиотека делает запрос:

ГдеКак выглядит
WebViewстраница ошибки с кодом net::ERR_CLEARTEXT_NOT_PERMITTED
HttpURLConnection (встроенный в Android)java.io.IOException: Cleartext HTTP traffic to example.com not permitted
OkHttp 3, 4, 5java.net.UnknownServiceException: CLEARTEXT communication to example.com not permitted by network security policy
DownloadManager, MediaPlayerотказ системных компонентов, по справке атрибута usesCleartextTraffic

Текст для HttpURLConnection взят из класса CleartextURLFilter в HttpHandler.java встроенного в Android OkHttp, текст для OkHttp — из RealRoutePlanner.kt. На стенде запрос через системный HttpHandler к запрещённому хосту вернул ровно эту строку.

Где проверка стоит в WebView

В url_request_http_job.cc Chromium проверка выполняется до создания сетевого запроса: если адрес не https и политика Android запрещает хост, вместо запроса возвращается ошибка −29. Перед ней стоит проверка HSTS: если сетевой стек знает, что хост работает только по https, адрес сначала переписывается на https, и до запрета дело не доходит.

Сама проверка в Chromium по умолчанию выключена. Её включает WebView: в aw_content_browser_client.cc написано, что для приложений с target API уровня O (Android 8, API 26) и выше запрет соблюдается. Справка атрибута usesCleartextTraffic говорит то же: WebView учитывает его для приложений с targetSdkVersion 26 и выше.

Важное следствие: запрос не уходит в сеть, даже за DNS. На стенде без сети разрешённый хост упал на разрешении имени (UnknownHostException), а запрещённый — сразу на проверке политики. В журнале сервера такого запроса не будет.

Почему HTTP запрещён по умолчанию

Правило по умолчанию задают две части системы.

Парсер манифеста (ParsingPackageUtils.java) выставляет флаг usesCleartextTraffic, если атрибут не указан: true при targetSdkVersion меньше 28, false — при 28 и выше. Затем, если файла network_security_config нет, ManifestConfigSource берёт значение этого флага как разрешение для всех хостов.

Если файл есть, разрешение по умолчанию берётся из NetworkSecurityConfig.getDefaultBuilder: HTTP разрешён только при targetSdkVersion ниже 28 (Android 9) и не для мгновенных приложений. Флаг из манифеста при этом не читается совсем.

targetSdkVersionФайл network_security_configusesCleartextTrafficHTTP к хосту не из файла
27 и ниженетне указанразрешён
27 и ниженетfalseзапрещён
28 и вышенетне указанзапрещён
28 и вышенетtrueразрешён
28 и вышеестьtrueзапрещён
27 и нижеестьлюбоеразрешён

Пятая строка — частая ловушка: разработчик ставит usesCleartextTraffic="true", добавляет файл ради сертификатов, и HTTP снова перестаёт работать. В справке это сказано одной фразой: атрибут игнорируется на Android 7.0 и выше, если указан файл network_security_config.

Стенд: код Android 16 и 17 на 11 конфигурациях

Эмулятор Android без аппаратной виртуализации не запустить, поэтому мы взяли сборки системного кода android-all для Android 16 и 17 из Maven Central — тот же код фреймворка, на котором работают тесты Robolectric. Классы XmlConfigSource, ApplicationConfig и NetworkSecurityConfig работали без изменений; подменили только системные часы, номер процесса и разбор IP-адреса, которые на обычной Java недоступны.

Каждый файл разбирался кодом Android, затем для 14 адресов вызывался isCleartextTrafficPermitted(host) — тот же метод, который вызывают WebView, HttpURLConnection и OkHttp. Приложение: targetSdkVersion 28, usesCleartextTraffic="true", сборка не отладочная.

Файлapi.example.comcdn.api.example.comsecure.example.com10.0.2.2192.168.1.10localhost (16 / 17)
только domain-config для api.example.comданетнетнетнетнет / да
base-config с разрешениемдададададада / да
example.com с поддоменамидададанетнетнет / да
example.com с поддоменами, вложенный secure.example.com с запретомдаданетнетнетнет / да
domain-config без атрибута до base-config с разрешениемдададададада / да
debug-overrides с разрешениемнетнетнетнетнетнет / да
10.0.2.2 и 192.168.1.0/24нетнетнетданетнет / да
*.example.com и http://example.orgнетнетнетнетнетнет / да
base-config с запретом, api.example.com с разрешениемданетнетнетнетнет / да
localhost с запретомнетнетнетнетнетнет / нет
example.com дваждыошибка разбора

«Да» — HTTP разрешён, «нет» — будет ERR_CLEARTEXT_NOT_PERMITTED. Без файла вовсе, с флагом false, Android 16 запретил все 14 адресов, а Android 17 — все, кроме localhost, 127.0.0.1 и ::1.

Для сравнения тот же первый файл при targetSdkVersion 27 разрешил все адреса: разрешение по умолчанию для старых приложений никуда не делось.

Пять ловушек в network_security_config

Звёздочки, диапазоны и схемы молча не работают. Записи *.example.com, 192.168.1.0/24 и http://example.org система приняла без единой ошибки и ни с одним адресом не сопоставила. Код ApplicationConfig.getConfigForHostname сравнивает имя целиком или, при includeSubdomains="true", проверяет, что адрес оканчивается на .имя. Для всех поддоменов пишут сам домен с includeSubdomains="true". Для локальной сети — каждый адрес отдельно.

debug-overrides не разрешает HTTP. В коде XmlConfigSource из раздела debug-overrides переносятся только доверенные сертификаты. Атрибут cleartextTrafficPermitted="true" в нём не действовал ни в обычной, ни в отладочной сборке. Чтобы HTTP работал только при разработке, кладут отдельный файл в ресурсы отладочной сборки (src/debug/res/xml/).

Повтор домена ломает весь файл. Если один домен указан в двух domain-config, разбор падает с ошибкой «example.com has already been specified». В XmlConfigSource такая ошибка оборачивается в исключение «Failed to parse XML configuration from …» — сетевая политика приложения не загружается вовсе.

Побеждает самое длинное совпадение. При вложенном domain-config secure.example.com с запретом внутри example.com с разрешением запрещены secure.example.com и его поддомены, а www.example.com разрешён. Порядок в файле не важен: domain-config, записанный до base-config, всё равно унаследовал от него разрешение.

Проверка без имени хоста строже. Метод isCleartextTrafficPermitted() без аргумента вернул «нет» для всех файлов, где хотя бы одному домену HTTP запрещён. Им пользуются старые библиотеки: OkHttp на Android 6 вызывает именно его, потому что проверка по хосту появилась в Android 7.

Android 17: localhost и конец usesCleartextTraffic

В коде Android 17 появились две перемены, которых нет в Android 16.

Неявное правило для localhost. Если приложение не задало правило для localhost, система добавляет его сама: HTTP разрешён. Справка Android перечисляет, что считается локальным адресом: localhost, ip6-localhost и числовые адреса петли, например 127.0.0.1 и [::1]. На стенде так и вышло. Свой запрет для localhost это правило не перекрывает: файл с cleartextTrafficPermitted="false" для localhost в Android 17 запретил все три адреса.

Адрес 10.0.2.2, по которому эмулятор обращается к компьютеру разработчика, под правило не попадает: он не локальный для самого телефона. Для сервера разработки на компьютере разрешение по-прежнему пишут явно.

Отказ от usesCleartextTraffic. В ManifestConfigSource Android 17 появилась проверка изменения совместимости DEPRECATE_USES_CLEARTEXT_TRAFFIC (номер 415007211): когда она включена, флаг из манифеста считается равным false. В сборке, которую мы проверяли, изменение выключено. Справка атрибута предупреждает, что он будет игнорироваться для приложений с targetSdkVersion 38 и выше, и советует задавать HTTP через network_security_config.

Как исправить ошибку разработчику

Лучший вариант — https

Если сервер умеет https, поменяйте адрес в приложении. Ошибка исчезнет без единой строки конфигурации, а данные перестанут идти открытым текстом. Если сервер не умеет https, сертификат Let's Encrypt выпускается бесплатно. Сертификат должен быть настоящим: самоподписанный приведёт к другой ошибке — NET::ERR_CERT_AUTHORITY_INVALID.

Разрешить HTTP одному хосту

Файл res/xml/network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">legacy.example.com</domain>
    </domain-config>
</network-security-config>

И ссылка на него в манифесте:

<application
    android:networkSecurityConfig="@xml/network_security_config"
    ... >

После этого usesCleartextTraffic в манифесте можно убрать: при наличии файла он всё равно не действует.

Сервер разработки и эмулятор

Для эмулятора, который обращается к компьютеру по 10.0.2.2, и для телефона в локальной сети указывают адреса по одному:

<domain-config cleartextTrafficPermitted="true">
    <domain>10.0.2.2</domain>
    <domain>192.168.1.10</domain>
</domain-config>

Такой файл лучше держать только в отладочной сборке, а в выпускной оставить запрет.

Разрешить всё

<base-config cleartextTrafficPermitted="true" />

Справка Android называет это небезопасной настройкой, которой стоит избегать. Вариант оправдан, только если приложение открывает адреса, которые заранее неизвестны, например браузер.

Найти, откуда идёт HTTP

  • В отладочной сборке включите StrictMode с detectCleartextNetwork() — справка Android рекомендует его для поиска незашифрованного трафика.
  • Проверьте перенаправления. Сервер, который отвечает на https перенаправлением на http://, приведёт WebView к той же ошибке: каждый новый адрес проходит проверку заново.
  • Проверьте адреса из ответов сервера: ссылки на картинки, видео и файлы часто хранятся в базе со схемой http://.

Что делать пользователю

Со стороны телефона ошибку не исправить: запрет записан в самом приложении, и никакой настройки Android для него нет. Поможет обновление приложения, если разработчик уже исправил адрес. Если обновления нет, напишите в поддержку приложения и укажите адрес, который не открылся. Очистка кэша, переустановка и другая сеть ничего не изменят: запрос не уходит в сеть вовсе.

Что это значит для владельца сайта

Если ваш сайт открывают в приложении через WebView — в мобильном банке, агрегаторе, мессенджере, — адрес с http:// там не откроется. Решение на стороне сайта одно: работать по https и везде ставить ссылки с https. Если сайт до сих пор отвечает по http, мы разбирали последствия в статье «Сайт до сих пор на http».

На поисковых роботов ошибка не влияет: это проверка внутри Android, а не ответ сервера.

Чем она отличается от похожих ошибок

ОшибкаЧто не так
ERR_CLEARTEXT_NOT_PERMITTEDприложение запрещает HTTP без шифрования
ERR_UNKNOWN_URL_SCHEMEWebView не умеет открывать ссылку с такой схемой
NET::ERR_CERT_AUTHORITY_INVALIDhttps есть, но сертификату не доверяют
ERR_NETWORK_ACCESS_DENIEDсистема не дала открыть сетевое соединение
ERR_BLOCKED_BY_CLIENTзапрос заблокировало расширение или само приложение

Границы замера

Стенд собран 20.10.2026: системный код из сборок android-all 16-robolectric-13921718 и 17-robolectric-15733970 (Maven Central) на Java 21, файлы конфигурации разбирались настоящим XmlConfigSource, проверка — настоящим ApplicationConfig, текст исключения — настоящим HttpHandler. На телефоне и в эмуляторе не проверяли: аппаратной виртуализации на сервере нет. Поведение WebView и OkHttp описано по их исходному коду, а не по запуску.

Источники

  • Chromium: net/base/net_error_list.h, net/url_request/url_request_http_job.cc, android_webview/browser/aw_content_browser_client.cc
  • Android: NetworkSecurityConfig.java, ManifestConfigSource.java, XmlConfigSource.java, ApplicationConfig.java, ParsingPackageUtils.java; встроенный OkHttp — HttpHandler.java
  • OkHttp: RealRoutePlanner.kt, AndroidPlatform.kt
  • Справка Android: «Network security configuration», атрибут android:usesCleartextTraffic элемента application, изменения поведения Android 9

Похожие ошибки

Коротко

ERR_CLEARTEXT_NOT_PERMITTED значит, что Android-приложение запретило себе HTTP без шифрования. С targetSdkVersion 28 это поведение по умолчанию, а если в манифесте есть network_security_config, атрибут usesCleartextTraffic не действует. Лучшее исправление — https; если нельзя, разрешение пишут в domain-config точным именем или адресом. Звёздочки, диапазоны и debug-overrides для этого не работают. В Android 17 localhost разрешён по умолчанию, а 10.0.2.2 — нет.

Вопросы и ответы

FAQ по теме

Что значит net::ERR_CLEARTEXT_NOT_PERMITTED?+
Приложение на Android попыталось открыть адрес по http, а сетевая политика приложения такие соединения запрещает. Код ошибки −29 в Chromium, его показывает WebView — встроенный браузер внутри приложения. Запрос не уходит в сеть: проверка стоит раньше.
Почему ошибка появилась после обновления targetSdkVersion?+
С Android 9 (API 28) HTTP без шифрования по умолчанию запрещён. Пока приложение указывало targetSdkVersion 27 или ниже, система разрешала его. После перехода на 28 и выше разрешение нужно задать явно — или, лучше, перевести адреса на https.
Я указал android:usesCleartextTraffic="true", но ошибка осталась. Почему?+
Если в манифесте указан файл network_security_config, атрибут usesCleartextTraffic не действует. На стенде с таким файлом и атрибутом "true" все хосты, не перечисленные в файле, остались запрещены. Разрешение надо писать в самом файле.
Как разрешить HTTP только для своего сервера разработки?+
Через domain-config с cleartextTrafficPermitted="true" и точным именем или IP-адресом сервера, например 10.0.2.2 для компьютера, на котором запущен эмулятор. Звёздочки и диапазоны адресов не работают: такие записи система принимает без ошибки, но ни с чем не сопоставляет.
Можно ли разрешить HTTP только в отладочной сборке через debug-overrides?+
Нет. Раздел debug-overrides добавляет только доверенные сертификаты. На стенде атрибут cleartextTrafficPermitted="true" в нём ничего не разрешил даже в отладочной сборке. Отладочный вариант файла кладут в ресурсы отладочной сборки.
Что делать обычному пользователю, если приложение показывает эту ошибку?+
Со стороны телефона это не исправить: запрет записан в самом приложении. Обновите приложение и сообщите разработчику адрес, который не открылся. Переустановка и очистка кэша не помогут.
Что изменилось в Android 17?+
Для localhost, 127.0.0.1 и ::1 появилось неявное разрешение, если приложение не задало для них своё правило. Адрес 10.0.2.2 под него не попадает. Справка Android также предупреждает, что атрибут usesCleartextTraffic перестанет действовать для приложений с targetSdkVersion 38 и выше.
Читайте также

Связанные материалы

SEO

ERR_SSL_KEY_USAGE_INCOMPATIBLE: назначение ключа не подходит

ERR_SSL_KEY_USAGE_INCOMPATIBLE — в сертификате сайта поле keyUsage не разрешает тот способ шифрования, о котором договорились браузер и сервер. Проверили 14 вариантов в Chrome 151, Firefox и curl и показали, как перевыпустить сертификат.

SEO

ERR_UNKNOWN_URL_SCHEME: неизвестная схема адреса

net::ERR_UNKNOWN_URL_SCHEME: браузер или приложение не знает, как открыть ссылку tel:, whatsapp:// или intent://. Разобрали по коду Chromium и как исправить.

SEO

NET::ERR_CERT_AUTHORITY_INVALID: браузер не доверяет сертификату

NET::ERR_CERT_AUTHORITY_INVALID — браузер не нашёл доверенного издателя сертификата. Проверили на стенде семь вариантов цепочки и разобрали живые сайты с ошибкой: заглушки хостинга, обрывы цепочки, сертификаты Минцифры.

SEO

Сайт до сих пор на http: что это значит для владельца

Обход 260 сайтов: 34 остаются на голом http, у 18 из них рядом живёт https-копия, а на 14 страницах форма собирает телефоны открытым текстом.