Fix Android “cleartext HTTP traffic not permitted” safely
Trace the effective network policy, migrate the endpoint to HTTPS, and keep any unavoidable cleartext exception narrow, testable, and temporary.
The exception java.io.IOException: Cleartext HTTP traffic to … not permitted is a policy decision, not a generic connectivity failure. A client attempted an unencrypted connection, and the effective Android network-security policy refused it before a useful HTTP exchange could occur. The durable repair is normally to make the endpoint work over HTTPS—not to switch off the guardrail.
Identify the request Android actually made
Start with evidence from the failing build and device. Record the final URI after redirects, the app’s targetSdkVersion, OS/API level, HTTP client, build variant, and whether a Network Security Configuration is packaged. A URL that looks secure in source can be rewritten by remote configuration, assembled with an http base URL, or redirected from HTTPS to HTTP.
adb logcat | grep -F "Cleartext HTTP traffic"
Use that only on a controlled development device, and sanitize logs before sharing them: query strings and headers can contain secrets. Inspect the merged manifest in Android Studio or the built APK rather than assuming the source manifest won. Library manifests and variant overlays can change the effective application attributes.
Reproduce against a harmless test account. Verify the destination independently:
curl --fail-with-body --location --proto '=https' --tlsv1.2 https://api.example.com/health
This checks the server path from the workstation; it does not prove the Android trust store, device clock, DNS, proxy, or client configuration is healthy. Also inspect every redirect. An HTTPS URL that returns a Location: http://… header still crosses into cleartext.
Understand which policy wins
For apps targeting API level 28 or later, Android’s platform default disallows cleartext. Up to target API level 27 it is allowed by default, but an explicit configuration, an instant/ephemeral environment, or another effective policy can still prohibit it. When a Network Security Configuration is present on API level 24 and later, Android documents that android:usesCleartextTraffic is ignored; the XML policy is the authority for covered platform components.
There are two important limits. First, enforcement is best-effort: low-level sockets and some third-party clients may not honor the platform declaration. Second, “works with this library” does not make HTTP safe. Cleartext lacks confidentiality, server authenticity, and tamper protection; a network observer can read or modify the response.
The production fix: serve and require HTTPS
- Provision a certificate whose subject names cover the API hostname, with the complete intermediate chain.
- Make the backend and every redirect available over HTTPS. Fix mixed-content URLs returned in feeds and remote configuration.
- Change the app’s base URL to
https://and reject unapproved schemes when parsing remote URLs. - Test on the oldest supported Android release, a current release, and devices with a clean trust store and realistic clock.
- Keep cleartext disabled so a later regression fails closed.
Do not “repair” certificate validation by installing a permissive trust manager or hostname verifier. That exchanges a visible outage for silent interception. For private development CAs, use Android’s <debug-overrides> so extra trust applies only when android:debuggable is true; never ship a debuggable production app.
If a legacy device truly requires HTTP
Sometimes an app must reach a local appliance that cannot be upgraded immediately. Treat this as a documented risk acceptance. Scope the exception to the exact hostname instead of enabling cleartext globally:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="false">legacy.example.net</domain>
</domain-config>
</network-security-config>
Reference it from the application element:
<application
android:networkSecurityConfig="@xml/network_security_config"
... >
Do not include subdomains unless every descendant is intended. Do not put credentials, personal data, update packages, executable instructions, or security decisions on that channel. Authenticate sensitive payloads at the application layer if migration cannot be immediate, understanding that metadata and replay risks remain. Put an owner and expiry date on the exception.
A manifest-wide android:usesCleartextTraffic="true" is broader and, with a Network Security Configuration on supported releases, may not even control the result. Reducing android:targetSandboxVersion, as suggested in older discussions, is not a sound fix: it weakens an unrelated security boundary and Android’s current manifest documentation marks that attribute deprecated. Preserve the stronger sandbox and correct the network path.
Verify the repair rather than the symptom
- Exercise login, refresh, upload, downloads, WebView content, media, and background jobs—not just one health call.
- Search the built artifact and remote configuration for unintended
http://endpoints. Allow known harmless strings such as XML namespace identifiers only after review. - Run a debug build with
StrictMode.VmPolicy.Builder.detectCleartextNetwork()where practical, and fail integration tests when an HTTP request leaves the client. - Capture a controlled network trace to confirm application traffic uses TLS and no fallback to HTTP occurs. Never capture real user credentials.
- Monitor cleartext exceptions, TLS handshake failures, redirect errors, and endpoint success rates by app and OS version without logging secrets.
If enabling the narrow rule does not change behavior, confirm the destination hostname matches the rule, the expected XML is packaged, and the client honors Network Security Configuration. An IP literal does not match a hostname rule. A VPN, proxy, captive portal, DNS failure, invalid certificate, or server outage produces a different failure and needs its own diagnosis.
Rollback and recovery
Release the HTTPS migration behind a controlled endpoint configuration, retain the last known-good signed build, and canary by app version. If the server rollout fails, roll the endpoint or certificate configuration back to the previous valid HTTPS state; do not reactivate global HTTP. If a time-limited domain exception must be used as an emergency bridge, ship it only after security approval, monitor its use, and prepare the removal release at the same time.
After recovery, rotate any credential or token that may have crossed cleartext, invalidate affected sessions, and investigate whether responses could have been altered. A restored feed does not undo prior exposure.
Attribution and current verification
This guide was prompted by david.s’s Stack Overflow question and Hrishikesh Kadam’s accepted answer, used under CC BY-SA. The answer’s narrow XML exception remains diagnostically useful, but its broad opt-in and sandbox-downgrade alternatives should not be the production default. Current behavior and syntax were independently checked against Android Developers’ official Network Security Configuration, <application> manifest reference, and cleartext communications risk guidance.
Primary source: Review the official reference ↗