Question

Allow HTTP and HTTPS in Android 9 Pie with Network Security Configuration

kotlinjavaandroidandroid-9.0-pieandroid-network-security-config

Question

In Android 9 Pie, unencrypted network requests are blocked by default, and the system expects apps to use TLS (HTTPS). If an app only makes HTTPS requests, it works normally.

How can an Android app allow both HTTP and HTTPS connections on Android 9 Pie, especially for apps such as browser-like apps that may need to load content from many different sites?

Short Answer

By the end of this page, you will understand why Android 9 blocks cleartext HTTP traffic by default, how to enable HTTP when needed, and the correct ways to configure this behavior using Android manifest settings and a network security configuration file.

Concept

Android 9 (API level 28) introduced a security change: cleartext traffic such as plain http:// is disabled by default for apps targeting modern Android versions. This helps protect users from network attacks like eavesdropping and man-in-the-middle tampering.

What is cleartext traffic?

Cleartext traffic means data sent without encryption. In practice, this usually means:

  • http://example.com → cleartext, not encrypted
  • https://example.com → encrypted with TLS

Why Android blocks HTTP by default

If traffic is not encrypted:

  • anyone on the same network may read it
  • attackers may modify responses
  • login tokens, cookies, and personal data may leak

Because of that, Android encourages apps to use HTTPS whenever possible.

But what if an app really needs HTTP?

Some apps, such as:

  • browser-like apps
  • apps loading user-provided URLs
  • tools for local network devices
  • legacy system integrations

may still need to support http:// URLs.

In those cases, Android lets you explicitly opt in to cleartext traffic.

Two common ways to allow HTTP

  1. Allow cleartext traffic globally using the manifest:
<application
    android:usesCleartextTraffic="true" ... />
  1. Use a Network Security Configuration for more control:
    • allow HTTP for specific domains
    • define custom trust behavior
    • keep the app safer than enabling everything blindly

For browser-like apps that can open arbitrary websites, global cleartext support may be necessary. For normal apps that call known servers, domain-specific configuration is usually better.

Mental Model

Think of Android network security like a building with a locked front door.

  • HTTPS is like entering through a secure door with identity checks.
  • HTTP is like leaving the door open so anyone nearby can watch or interfere.
  • Starting with Android 9, the building manager locks that insecure door by default.
  • If your app truly needs it, you must explicitly tell Android: "This app is allowed to use that door."

That explicit permission can be broad for the whole app or limited to specific destinations.

Take Quiz

Syntax and Examples

The main configuration options are in the Android manifest and, optionally, a network security config XML file.

1. Allow all cleartext traffic globally

Use this when your app truly needs to access arbitrary http:// URLs.

<application
    android:usesCleartextTraffic="true"
    ... >
</application>

Example manifest

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:usesCleartextTraffic="true">

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
</manifest>

This tells Android that the app may use both HTTP and HTTPS.

2. Allow HTTP using a network security configuration

First, create res/xml/network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true" />
</network-security-config>

Then reference it in the manifest:

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

This also allows cleartext traffic for the app.

3. Allow HTTP only for specific domains

This is safer for most apps.

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

Now HTTP is allowed for example.com and its subdomains, while other traffic stays protected.

4. Example Java code making a request

URL url = new URL("http://example.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();

int responseCode = connection.getResponseCode();
System.out.println("Response code: " + responseCode);

If cleartext traffic is not enabled, this request may fail on Android 9+ when targeting API 28 or above.

Step by Step Execution

Consider this setup:

<application
    android:usesCleartextTraffic="true"
    ... />

And this code:

URL url = new URL("http://example.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();

What happens step by step

  1. The app starts.
  2. Android reads the app manifest.
  3. It sees android:usesCleartextTraffic="true".
  4. Android allows the app to make unencrypted HTTP requests.
  5. Your code creates a URL with the http:// scheme.
  6. openConnection() prepares a network connection.
  7. connect() tries to contact the server.
  8. Because cleartext traffic is permitted, Android does not block the request just for being HTTP.
  9. The request succeeds or fails based on normal network conditions, server availability, DNS, and permissions.

What if the setting is missing?

If your app targets Android 9 behavior and tries this same HTTP request without allowing cleartext traffic, Android may reject it with an error such as cleartext traffic not permitted.

Real World Use Cases

Here are common situations where this matters:

Browser-like apps

A browser or web viewer may open URLs typed by users. Since users may enter both http:// and https://, the app may need global HTTP support.

Local network devices

Apps that connect to routers, cameras, printers, IoT devices, or internal admin panels often use plain HTTP on local networks.

Legacy enterprise systems

Some organizations still expose internal APIs or dashboards over HTTP. An Android app used in that environment may need explicit cleartext support.

Development and testing

During local development, a backend may run on a machine using HTTP only. The app may need temporary support for local cleartext traffic.

Hybrid apps or WebView-based tools

Apps that display external pages or custom portals may need to support whatever protocol the target site provides.

Take Quiz

Real Codebase Usage

In real projects, developers usually avoid enabling all HTTP traffic unless the app truly behaves like a browser.

Common patterns

1. Prefer HTTPS by default

Most production apps call known APIs. These apps usually keep HTTP blocked and use HTTPS everywhere.

2. Allow only known domains

A safer pattern is to use network_security_config.xml with a domain-config entry for legacy services.

3. Separate debug and release behavior

Teams often allow HTTP in debug builds for local development, but block it in release builds.

Example pattern:

  • debug build: allow 10.0.2.2 or internal test domain
  • release build: HTTPS only

4. Use guard logic for user-entered URLs

If users can enter URLs, developers often validate them first:

String input = "http://example.com";
if (input.startsWith("http://") || input.startsWith("https://")) {
    // proceed
} else {
    // reject invalid URL
}

5. Be explicit in WebView apps

For apps using WebView, developers still need to consider Android cleartext policy when loading HTTP content.

6. Keep security review in mind

Allowing global HTTP means any part of the app can make insecure requests. In real codebases, this setting should be documented and justified.

Common Mistakes

1. Assuming Internet permission is enough

Beginners often think this is only about adding internet permission.

<uses-permission android:name="android.permission.INTERNET" />

This permission is required, but it does not override Android 9 cleartext restrictions.

2. Forgetting to set the config on the <application> tag

Creating network_security_config.xml is not enough by itself.

Broken example:

<network-security-config>
    <base-config cleartextTrafficPermitted="true" />
</network-security-config>

If the manifest does not reference it, Android will not use it.

Correct:

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

3. Allowing all HTTP when only one domain needs it

This works, but it is less secure:

<application android:usesCleartextTraffic="true" ... />

If only one legacy domain needs HTTP, prefer a domain-specific config.

4. Testing only on old Android versions

An app may work on Android 8 and fail on Android 9+ because cleartext policy changed.

5. Using HTTP for sensitive data

Even if you can enable HTTP, you should not use it for:

  • passwords
  • tokens
  • personal information
  • payment data

6. Confusing HTTPS certificate issues with HTTP policy

If HTTPS fails, the cause may be:

  • invalid certificate
  • hostname mismatch
  • expired certificate
  • untrusted CA

That is different from the cleartext HTTP restriction.

7. Expecting arbitrary app-wide behavior without checking libraries

Some networking libraries follow Android platform rules. If HTTP is blocked, the library may throw an exception that looks library-specific, but the root cause is still cleartext policy.

Comparisons

ApproachWhat it doesBest forSecurity level
android:usesCleartextTraffic="true"Allows cleartext traffic app-wideBrowser-like apps, broad HTTP supportLowest
networkSecurityConfig with base-configAllows cleartext traffic through config XMLApps that want centralized policyLow
networkSecurityConfig with domain-configAllows HTTP only for specific domainsMost normal apps with a few legacy endpointsBetter
HTTPS onlyBlocks HTTP and uses encrypted traffic onlyModern apps and public APIsBest

Manifest flag vs network security config

FeatureManifest flagNetwork security config
Simple to set upYesSlightly more work
Fine-grained domain controlNoYes
Better for long-term maintenanceLimitedYes
Good for browser-like appsYesSometimes

HTTP vs HTTPS

| Protocol | Encrypted | Safe for sensitive data | Recommended | |---|---|---| | HTTP | No | No | Only when unavoidable | | HTTPS | Yes | Yes, when properly configured | Yes |

Take Quiz

Cheat Sheet

Quick reference

Allow all HTTP and HTTPS

<application
    android:usesCleartextTraffic="true"
    ... />

Allow cleartext with network security config

AndroidManifest.xml

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

res/xml/network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true" />
</network-security-config>

Allow HTTP for one domain only

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

Still required

<uses-permission android:name="android.permission.INTERNET" />

Rules to remember

  • Android 9 blocks cleartext HTTP by default.
  • HTTPS is not affected by this restriction.
  • usesCleartextTraffic="true" enables HTTP app-wide.
  • networkSecurityConfig gives more control.
  • Prefer domain-specific HTTP access when possible.
  • Never send sensitive data over HTTP.

Common error clue

If you see a message like Cleartext HTTP traffic not permitted, your app is trying to use HTTP without the required configuration.

FAQ

Why does HTTP stop working on Android 9?

Android 9 blocks cleartext traffic by default to improve security and protect user data on insecure networks.

How do I allow both HTTP and HTTPS in Android?

Add android:usesCleartextTraffic="true" to the <application> tag, or configure a network security config XML file.

Is usesCleartextTraffic="true" safe?

It is functional, but less secure than allowing HTTP only for specific domains. Use it only when the app genuinely needs broad HTTP access.

Should I use the manifest flag or network security config?

Use the manifest flag for simple app-wide behavior. Use network security config when you want more control, especially domain-based rules.

Does this affect WebView too?

It can. If your app loads HTTP content in a WebView, you still need to consider Android cleartext traffic policy.

Do I still need the INTERNET permission?

Yes. Cleartext settings do not replace <uses-permission android:name="android.permission.INTERNET" />.

Can I allow HTTP only in debug builds?

Yes. Many teams do that for local development and keep release builds HTTPS-only.

If I enable HTTP, will all requests work?

Not necessarily. Requests can still fail because of DNS errors, server issues, timeouts, firewall rules, or invalid HTTPS certificates.

Take Quiz

Mini Project

Description

Build a small Android app configuration that can load both HTTP and HTTPS URLs. This demonstrates how Android 9 network security rules work and how to explicitly allow cleartext traffic for browser-like behavior or legacy endpoints.

Goal

Configure an Android app so it can access both http:// and https:// URLs on Android 9 and above.

Requirements

  1. Add the INTERNET permission to the app.
  2. Enable cleartext traffic for the application.
  3. Create a simple Java example that opens a URL connection.
  4. Make sure the setup works for both HTTP and HTTPS URLs.
Take Quiz

Keep learning

Related questions

View more