🔍 Compatibility

Android WebView Compatibility Checker

Paste your website URL and get an instant report. Know exactly which issues will break your WebView app — before you build.

!

The Free App Maker WebView Compatibility Checker fetches your URL and reports the things that break an Android WebView app: cleartext HTTP, a missing viewport tag, login walls, slow responses and thin server-rendered HTML. It cannot see inside the WebView, so this page also documents what Android blocks by default — third-party cookies, Google OAuth, camera access and file uploads. Free, no account.

Written by the Free App Maker team at My Mind Studio · Last verified 26 August 2026

Enter any public URL. The checker fetches the page server-side to inspect headers and content.

Checking your site for WebView compatibility…

What gets checked

7 compatibility checks, explained

HTTP Response Code

The server must return a 200 OK. A 401, 403, or 5xx means users will see an error screen inside the app.

Embedding headers (X-Frame-Options / CSP)

These govern framing, not top-level loads, so on their own they rarely blank a WebView. They are reported because they flag an origin that restricts embedding — and because the same rule often blocks unfamiliar user agents too.

HTTPS Transport

Cleartext support is off by default for apps targeting Android 9 and above, so an http:// URL needs an explicit opt-in that most wrappers do not make.

Mobile Viewport Meta Tag

Without <meta name="viewport">, the page renders at desktop width inside the app and appears tiny.

Login Wall Detection

If the first screen requires a login, users who haven't created an account will hit a wall immediately on open.

Response Time

Pages over 4 seconds feel broken on a mobile network. The app should load in under 2 seconds for a good first impression.

HTML Content Volume

Pages that render entirely via JavaScript may appear blank on slow connections. Server-rendered HTML loads reliably in WebView.

Sources: MDN — X-Frame-Options and Android Developers — Network security configuration, both checked 26 Aug 2026.

What a WebView is, and what it is not

A WebView is an Android view that renders web pages inside your own app. It uses the same Chromium engine that powers Chrome on the device, which is why people assume it behaves like Chrome. It does not, and the gap is where every surprise on this page comes from.

Android's own comparison of WebView against Custom Tabs puts the difference in one word. A WebView's data and sessions are “Sandboxed. It doesn't share cookies or logins with the user's main browser.” Custom Tabs, by contrast, are “Shared. It uses the user's default browser session, including cookies and saved passwords.” Chrome's own documentation is blunter still, noting that WebViews “don't support all features of the web platform, don't share state with the browser and add maintenance overhead”.

Two consequences follow immediately, and they explain most of the support tickets a new WebView app generates:

A WebView also starts with more switched off than people expect. Android's WebView guide states plainly that “JavaScript is disabled in a WebView by default,” and the reference for setDomStorageEnabled gives a default of false, meaning localStorage and sessionStorage are unavailable until the app turns them on. A competent wrapper enables both. It is worth knowing they are opt-in, because a hand-rolled wrapper that forgot is the classic cause of a blank screen with no error.

Sources: Android Developers — In-app browsing using embedded web, Android Developers — Overview of Android Custom Tabs and Android Developers — Build web apps in WebView, all checked 26 Aug 2026.

The compatibility matrix at a glance

Every row below is expanded further down the page with its source. Treat “partly” as “works, but only because the app implemented something” — which means it depends entirely on which wrapper you use.

CapabilityIn a WebViewThe short reason
HTTPS pagesWorksThe normal case. Cleartext HTTP is the one that needs an opt-in.
Mixed content on an HTTPS pageBlockedApps targeting Android 5.0+ default to MIXED_CONTENT_NEVER_ALLOW.
First-party cookiesWorkssetAcceptCookie is true by default.
Third-party cookiesOff by defaultApps targeting Android 5.0+ default to disallowing them.
Sign in with GoogleBlocked by GoogleGoogle's OAuth policy forbids embedded user-agents.
Card payment redirects and 3-D SecureUsually worksTop-level redirects are fine; app handoffs and iframe challenges are not.
Camera and microphonePartlyNeeds a manifest permission, a runtime grant and a WebView callback.
GeolocationPartlySame chain, plus HTTPS-only from Android 7.0.
File upload fieldsPartlyWebView cancels every file request unless the app implements the chooser.
Passkeys and WebAuthnPartlyNeeds AndroidX WebKit 1.12.0+, digital asset linking and an app-side opt-in.
target="_blank" and window.openChanges meaningTreated as a top-level navigation that replaces the current page, by default.
tel:, mailto:, intent: linksPartlyOnce the app sets a WebViewClient, routing them becomes the app's job.
Video autoplayNeeds a gesturesetMediaPlaybackRequiresUserGesture defaults to true.
Service workers and offline cacheWorksManaged by ServiceWorkerController since Android 7.0.
Web push notificationsNot supportedPushManager and showNotification are unsupported in WebView.
PWA install promptNo surfaceInstalling is browser UI; a WebView has none, and the app is already installed.

Mixed content: the silent one

Mixed content means an HTTPS page pulling a subresource over plain http://. In a WebView this is not a warning, it is a deletion: the image never appears, the script never runs, the font falls back, and nothing in the interface tells the user why.

Android's reference for WebSettings.setMixedContentMode spells out the default: apps targeting Android 4.4 KitKat or below default to MIXED_CONTENT_ALWAYS_ALLOW, while “Apps targeting Build.VERSION_CODES.LOLLIPOP default to MIXED_CONTENT_NEVER_ALLOW.” The same page adds that never-allow is “the preferred and most secure mode of operation” and that always-allow is “strongly discouraged”. Google Play separately requires that, starting 31 August 2026, “New apps and app updates must target Android 16 (API level 36) or higher to be submitted to Google Play”, so effectively every WebView app you ship is in the strict bucket.

Separately, the transport itself is restricted. Android's network security configuration documentation states that “Starting with Android 9 (API level 28), cleartext support is disabled by default,” where before Android 8.1 it was enabled. So an http:// site is not merely inadvisable in an app — it will not load at all unless the app deliberately opts back in.

Where it actually comes from

Almost nobody hard-codes http:// in their own markup any more. The offenders are inherited:

Protocol-relative URLs (//cdn.example.com/x.js) are safe, because they inherit the page's HTTPS. The ones to hunt for are absolute. A search of your rendered HTML for "http:// finds most of them in a minute.

The edge case people missFixing the page you tested is not the same as fixing the site. Mixed content is per-page, and the offending asset is often on a checkout step, an account page or a blog post — somewhere a homepage check never reaches. Load several real pages inside a WebView with DevTools attached and read the console, not just the front page.

Sources: Android Developers — WebSettings.setMixedContentMode, Android Developers — Network security configuration and Android Developers — Meet Google Play's target API level requirement, all checked 26 Aug 2026.

Cookies and sessions behave differently

Two distinct cookie facts matter, and confusing them wastes days.

1. The WebView has its own cookie jar

It is not Chrome's. Android's guidance describes the WebView as sandboxed and says it “doesn't share cookies or logins with the user's main browser”. Everyone who installs your app is a logged-out visitor on day one, however long they have been a customer on the web. Plan for that: the first screen a user of your new app sees is your login screen, so make sure it is a good one, and expect a spike in password resets in the first week.

2. Third-party cookies are refused by default

Android's CookieManager reference states that “Apps that target Build.VERSION_CODES.KITKAT or below default to allowing third party cookies. Apps targeting Build.VERSION_CODES.LOLLIPOP or later default to disallowing third party cookies,” and that the policy is set per WebView instance. First-party cookies are unaffected — setAcceptCookie is documented as “By default this is set to true and the WebView accepts cookies.”

What relies on cross-site cookies, and therefore may quietly fail:

  • An embedded checkout or card field served in an iframe from your payment provider's domain.
  • Single sign-on that keeps its session on a separate identity domain.
  • Support chat, booking and scheduling widgets loaded from the vendor's origin.
  • Analytics or personalisation that reads a cookie set on another site.
SameSite=None does not rescue thisMDN's Set-Cookie reference describes SameSite=None as “Send the cookie with both cross-site and same-site requests,” adding that “The Secure attribute must also be set when using this value.” That attribute is what makes a cross-site cookie legal for a browser to send. It is not permission for the WebView to accept one — the Android-side default is a separate gate, and it is closed.

The reliable fix is architectural rather than clever: move anything session-critical onto your own origin. A redirect-based checkout on your domain survives; an iframe on someone else's domain that needs to read its own cookie may not.

Sources: Android Developers — CookieManager and MDN — Set-Cookie, both checked 26 Aug 2026.

OAuth: Google blocks sign-in from embedded webviews

This is the single most consequential thing on the page, and the one most likely to be discovered after launch. It is not a bug, a user-agent quirk or something a better wrapper can work around. It is policy, enforced at Google's servers.

Google's OAuth 2.0 policies state: “A developer must not direct a Google OAuth 2.0 authorization request to an embedded user-agent under the developer's control.” The policy explains what counts as embedded — environments that let a developer “insert arbitrary scripts, alter the default routing of a request to the Google OAuth server, or access session cookies” — and requires that the user can verify they are really talking to Google.

When it is violated, Google's native-app documentation describes the outcome as the disallowed_useragent error, raised because “The authorization endpoint is displayed inside an embedded user-agent disallowed by Google's OAuth 2.0 Policies.” Your user taps “Sign in with Google” and gets an error page.

What to do instead

Android's own documentation points the same way. Custom Tabs, it says, “are well-suited for third-party sign-in flows (such as ‘Sign in with Google' or ‘Sign in with Facebook') as the browser handles credentials securely,” and because a Custom Tab “shares cookies with the user's default browser, users don't have to sign in again to sites they have already visited.” Practically, that gives you three options:

  1. Offer an email or password path. If Google is one of several ways in, WebView users take another door and nothing else changes. This is the cheapest fix by a wide margin.
  2. Use a wrapper that hands the auth URL to a Custom Tab or the system browser and returns the session afterwards. This works, but it is a real integration, not a checkbox.
  3. Reconsider the wrapper for that flow. If your product cannot exist without federated sign-in on the first screen, a WebView shell is the wrong shape for it.
Why almost everyone tests this wrongYou test on your own phone, where your site already set a session cookie, so you are never shown the Google screen and the app looks perfect. The person who hits the wall is a brand-new user on day one. Clear the app's data, or use a device that has never visited your site, and sign up from scratch before you decide this page does not apply to you.

Other identity providers make their own decisions, and several follow the same reasoning about embedded user-agents. Do not assume that because one provider works, another will — test each one you offer.

Passkeys and WebAuthn are a separate opt-in

If you have moved your sign-in to passkeys, that is a second thing to check, and it is not covered by the OAuth policy above. Passkeys in a WebView run through Android's Credential Manager, and Android's guide for that states it is “supported natively in the android.webkit.WebView library in version 1.12.0 and later” — that is the AndroidX WebKit library the app depends on, not the WebView on the user's phone.

Three things have to be true, and all three are app-side:

That last requirement is the one to notice before you plan around it: it assumes the app and the site belong to the same owner, and it is a piece of configuration on your domain, not something a wrapper can invent for you. If passkeys are the only way into your product, keep a password or emailed-link route available for app users until you have tested this end to end on a real device.

Sources: Google Identity — OAuth 2.0 Policies, Google Identity — OAuth 2.0 for Mobile & Desktop Apps, Android Developers — In-app browsing using embedded web and Android Developers — Authenticate users with WebView, all checked 26 Aug 2026.

Payment redirects and 3-D Secure

Card payments in Europe, India and a growing list of other markets involve a strong-authentication step: the payment page sends the customer to the card issuer's own domain for a challenge, then back to your return URL. Inside a WebView that chain has three distinct failure modes, and only one of them is really about the WebView.

Failure 1: the wrapper ejects the customer mid-payment

By default a WebView keeps everything in-app. Android's guide is explicit: “All links the user taps load in your WebView. If you want more control over where a clicked link loads, create your own WebViewClient that overrides the shouldOverrideUrlLoading method.” Many wrappers use that hook to send any off-domain URL to the system browser — a sensible-sounding rule that is fatal here, because the bank's challenge page is off-domain. The customer is thrown into Chrome, completes the challenge there, and the return never comes back to your app. Whatever rule your wrapper uses must allow the payment and issuer domains to stay inside.

Failure 2: the challenge is an iframe that needs a cross-site cookie

Where the challenge renders in an iframe on the issuer's domain rather than as a full-page redirect, it can depend on a cookie set on that third-party origin — and third-party cookies are off by default, as above. A redirect-based flow avoids the problem entirely, which is why it is worth choosing when your provider offers both.

Failure 3: the handoff to a bank or wallet app

UPI, wallets and many bank apps are launched from the web with a custom URI scheme or with Android's intent: syntax. Chrome documents that syntax, including the S.browser_fallback_url extra for “when an intent isn't resolved or an external application doesn't launch”, but that resolution is behaviour Chrome implements. A bare WebView has no handler for an unfamiliar scheme, so unless the app intercepts the navigation in shouldOverrideUrlLoading and fires the intent itself, the button simply does nothing — often with an unknown-scheme error page.

One more thing worth knowing before you plan around the Payment Request API: MDN's compatibility data lists PaymentRequest as arriving in Android WebView at version 136, far later than Chrome for Android. Plenty of real devices in the wild carry older WebView builds, so treat it as a progressive enhancement rather than your checkout.

How to actually test thisSandbox cards rarely reproduce the redirect chain and never reproduce a wallet handoff. Put one real, small, refundable transaction through the app on a real device, including the challenge step. It is the cheapest insurance on this page.

Sources: Android Developers — Build web apps in WebView, Chrome for Developers — Android Intents with Chrome and MDN — PaymentRequest browser compatibility, all checked 26 Aug 2026.

Camera, microphone and geolocation

These work in a WebView, but only when three separate gates are open. Miss one and the failure is usually silent — a camera preview that stays black, a location that never resolves.

  1. The app declares the permission. Nothing the web page does can conjure a permission the APK never asked for.
  2. The user grants it at the Android prompt. Camera, microphone and location are runtime permissions, which Android's permissions overview defines as “also known as dangerous permissions”, adding: “you need to request runtime permissions in your app before you can access the restricted data or perform restricted actions.” It also warns not to assume a previous grant still holds — permissions can be revoked.
  3. The app passes the grant through to the page. This is the step unique to WebViews. Your page's getUserMedia() call surfaces to the app as WebChromeClient.onPermissionRequest, described as notifying “the host application that web content is requesting permission to access the specified resources”. The resources are named constants — RESOURCE_VIDEO_CAPTURE (“Resource belongs to video capture device, like camera”) and RESOURCE_AUDIO_CAPTURE (“Resource belongs to audio capture device, like microphone”). If the app does not implement that callback and grant them, the page is refused even though the user already said yes to Android.

Geolocation has its own documented chain. WebSettings.setGeolocationEnabled defaults to true, but the reference lists two further requirements: “an application must have permission to access the device location” (ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION), and “an application must provide an implementation of the WebChromeClient.onGeolocationPermissionsShowPrompt callback to receive notifications that a page is requesting access to location via the JavaScript Geolocation API.”

HTTPS is not optional for locationAndroid's documentation for that callback states that for apps targeting Android 7.0 and later it “is only called for requests originating from secure origins such as https. On non-secure origins geolocation requests are automatically denied.” If your site is still on HTTP, location is dead in the app before anyone taps anything.

The practical upshot: “it works in Chrome on my phone” proves nothing. Chrome has already declared these permissions and implements every callback. Whether your app does is a property of the wrapper you chose, so test the actual feature in the actual app.

Sources: Android Developers — Permissions on Android, Android Developers — WebChromeClient, Android Developers — PermissionRequest and Android Developers — WebSettings.setGeolocationEnabled, all checked 26 Aug 2026.

File uploads and downloads

If your site has a profile photo, a document upload, a “attach a file” support form or an export button, read this before you ship.

An <input type="file"> in a WebView does not open a picker on its own. Android routes it to WebChromeClient.onShowFileChooser, which is documented as being called when “The web page has requested to either upload or save a file, such as from a 'file' input in an HTML form or due to a JavaScript API call.” The important sentence is the last one in that entry: “The default behavior is that WebView will cancel all file requests.”

So in a wrapper that has not implemented the callback, the input renders normally, the user taps it, and nothing happens at all. No error, no picker. It is one of the most confusing failures to debug from the outside because the page looks completely healthy.

Downloads fail from the opposite direction. A WebView does not save files by itself; WebView.setDownloadListener exists to register a handler “to be used when content can not be handled by the rendering engine, and should be downloaded instead”. Without one, a link to a PDF, CSV or ZIP does nothing useful. Anything your site hands users as a file — invoices, tickets, reports — depends on the app implementing this.

Both are solvable, and good wrappers solve them. The point is that they are app-side features, not web-side ones, so “does upload work?” is a question about the tool you build with. Test it with a real photo and a real download before launch.

Sources: Android Developers — WebChromeClient.onShowFileChooser and Android Developers — WebView.setDownloadListener, both checked 26 Aug 2026.

What target="_blank" actually does in a WebView

The folklore says links with target="_blank" “do nothing” inside an app. The documented behaviour is more interesting than that, and more disruptive, because the link does something — just not what you designed.

Android's reference for WebSettings.setSupportMultipleWindows gives the default as false and then says exactly what that means: “When multiple window support is disabled, requests to open new windows (either from the window.open() JavaScript API or from links with target="_blank") will instead be treated as top-level navigations, replacing the current page in the same WebView.”

So the new-window link does not open a window. It navigates the one view you have. On the web that is a minor difference. In an app it is a trap, because the tab the user expected to close is not there:

The mirror-image failure happens if the app switches multiple-window support on. The same reference notes that when it is enabled, WebChromeClient.onCreateWindow “must be implemented by the application to handle the creation of new windows” — and that callback's own documentation says “The default implementation of this method does nothing and hence returns false.” Turn the setting on without implementing the callback and you get the failure everyone expected in the first place: the link genuinely does nothing.

Pop-ups your own code opens

There is a second, independent gate. setJavaScriptCanOpenWindowsAutomatically is documented as defaulting to false, with the consequence spelled out: “attempts without a user gesture will fail and do nothing.” The same entry adds that this “is not affected by the setSupportMultipleWindows(boolean) setting; the user gesture requirement is enforced even if multiple windows are disabled.”

In practice that means a window.open() fired from a timer, from an analytics callback, or from a promise that resolves a beat after the tap — a common pattern in payment SDKs and “open the receipt” flows — is dropped without an error. The fix on the web side is the same one modern browsers already push you toward: open windows synchronously, inside the click handler, not after an await.

The cheap auditSearch your rendered HTML for target="_blank" and your JavaScript for window.open. For each hit, decide what should happen inside an app: keep it in the WebView, or hand it to the system browser deliberately. The answer is usually different for your own pages than for third-party ones, and that decision is a property of the wrapper you build with — worth checking before you pick one.

Sources: Android Developers — WebSettings.setSupportMultipleWindows and Android Developers — WebChromeClient.onCreateWindow, both checked 26 Aug 2026.

Non-web links and video playback

Two more places where the page is fine and the app is the missing piece.

tel:, mailto:, sms: and app links

A “Call us” button, an email link and a WhatsApp or maps link are all navigations to a scheme that is not HTTP. Android's WebViewClient reference describes the starting position: “If a WebViewClient is not provided, by default WebView will ask Activity Manager to choose the proper handler for the URL.” Left completely alone, then, those links work.

The catch is that essentially every wrapper does provide a WebViewClient — that is the hook used to keep navigation inside the app, apply an allow-list of domains, or show an offline screen. Once it exists, the default handling is gone and routing those schemes is the app's job. The same reference warns what happens if the app just lets the navigation proceed: “This method may be called for subframes and with non-HTTP(S) schemes; calling WebView.loadUrl(String) with such a URL will fail.”

The symptom is a phone-number button that does nothing on some apps and dials on others, from the identical HTML. It is not your markup. It is whether the wrapper recognises the scheme and fires the right Android intent.

The edge case that catches payment flowsThe same documentation carries a note that is easy to skim past: “This method is not called for POST requests.” If your checkout navigates off-site by POSTing a form to your payment provider — a very common pattern — the wrapper's routing rules never see that navigation at all. Any allow-list or “open externally” logic silently does not apply to it. Worth knowing before you conclude your domain rules are airtight.

Video will not autoplay

WebSettings.setMediaPlaybackRequiresUserGesture is documented with “The default is true.” A WebView requires a user gesture before it plays media, so the autoplaying hero video, the muted background loop and the carousel that starts itself all sit on their poster frame until somebody taps. If the design depends on motion, give it a real poster image and a visible play control rather than assuming the app will behave like the site.

Fullscreen is app-side too. When a video goes fullscreen, Android tells the app through WebChromeClient.onShowCustomView, and the documentation is explicit about the handover: “After this call, web content will no longer be rendered in the WebView, but will instead be rendered in view,” which the app “should add … to a Window which is configured with WindowManager.LayoutParams.FLAG_FULLSCREEN.” A wrapper that does not implement it gives you the classic bug where the fullscreen button produces a black rectangle and no way out.

Sources: Android Developers — WebViewClient.shouldOverrideUrlLoading, Android Developers — WebSettings.setMediaPlaybackRequiresUserGesture and Android Developers — WebChromeClient.onShowCustomView, all checked 26 Aug 2026.

Service workers, push and the PWA install prompt

Service workers do work — this surprises people

The common belief that service workers are unavailable in a WebView is out of date. Android ships android.webkit.ServiceWorkerController, added in API level 24 (Android 7.0), described simply as a class that “Manages Service Workers used by WebView”, with a hook for intercepting requests from them. Your offline cache and your precached shell generally behave as they do in the browser.

Web push does not

MDN's compatibility data lists PushManager as unsupported in Android WebView, and the same for ServiceWorkerRegistration.showNotification(), the only way Chrome for Android allows a notification to be shown at all. So the push code that works on your website will not deliver a notification inside the app. If notifications are a reason you want an app, they have to come from a native channel — which is a real feature of the app, not something your existing web code can supply.

The install prompt has nowhere to appear

Installing a progressive web app is a browser affordance: it lives in the browser's interface, alongside the address bar and the menu. A WebView deliberately has none of that. There is also nothing sensible for it to do — the person looking at your page inside your Android app has already installed your Android app. In practice the banner does not show, and the correct response is to hide your own install prompt for the app's user agent rather than to chase it.

Related: manifest properties that ask the browser to change its own chrome — display: standalone, theme colours applied to browser UI — have nothing to act on in a WebView, because the app supplies the frame. If what you want is genuinely browser-grade PWA behaviour on Android, Google's route is a Trusted Web Activity, where the content, in Chrome's words, “comes from the web: they're rendered by the user's browser.” That is a different architecture from a WebView, with different trade-offs — a Trusted Web Activity requires you to verify ownership of the domain.

Sources: Android Developers — ServiceWorkerController, MDN — PushManager browser compatibility and Chrome for Developers — Trusted Web Activity, all checked 26 Aug 2026.

“The WebView” is not one thing

It is tempting to think of the WebView as a fixed target that ships with the Android version. It is not. Android's guide to managing WebView objects notes that “Starting in Android 7.0 (API level 24), users can choose among several different packages for displaying web content in a WebView object,” and the same page adds that the lookup for which package is in use “can return null if the device is set up incorrectly; doesn't support using WebView … or lacks an updatable WebView implementation.”

Two practical consequences follow.

The rendering engine version is the user's, not yours

Your APK does not carry a browser. The engine that renders your site belongs to the device, and its version varies across your install base for reasons you do not control. That is usually invisible — until you depend on a recent web platform feature.

The clearest example is on this page already. MDN's compatibility data records the Payment Request API arriving in Chrome for Android at version 53 and in Android WebView only at version 136. A feature that has been safe on the mobile web for years can still be missing from a WebView on a phone that has not been updated. The discipline is ordinary progressive enhancement: feature-detect rather than version-detect, and never let the only path through a checkout, a login or an upload depend on an API you have not confirmed on a real, unremarkable device.

Safe Browsing can put a warning in front of your page

Android's guide states that “WebView objects verify URLs using Google Safe Browsing, which lets your app show users a warning when they try to navigate to a potentially unsafe website,” and that “the default value of EnableSafeBrowsing is true.” If a URL on your domain — or a third-party domain you embed — gets flagged, the interstitial appears inside your app, over your brand, and nothing about your HTML changes it. Keeping your domain clean is an app-availability issue, not just an SEO one.

Sources: Android Developers — Manage WebView objects and MDN — PaymentRequest browser compatibility, both checked 26 Aug 2026.

Technically compatible is not the same as allowed on Google Play

A site can pass every check on this page and still be the wrong thing to publish. If you intend to list the app on Google Play rather than distribute the APK yourself, there is a policy question sitting alongside the technical one, and it is better answered before you build than after a rejection.

The relevant clause is in Google Play's Spam policy, under Webviews and Affiliate Spam: “We don't allow apps whose primary purpose is to drive affiliate traffic to a website or provide a webview of a website without permission from the website owner or administrator.” The example Google gives is an app that “simply provides a webview” of a large retailer's site.

Read the qualifier carefully, because it is the whole clause: without permission from the website owner or administrator. Wrapping a site you own or run is not what that sentence prohibits. Wrapping somebody else's — a shop you are an affiliate of, a news site, a forum you like — is.

A second clause is worth knowing if you are thinking about publishing several similar apps. Under Repetitive Content, the same policy says: “We don't allow apps that merely provide the same experience as other apps already on Google Play,” and advises that where such apps “are each small in content volume, developers should consider creating a single app that aggregates all the content.”

Alongside the content rules there is a moving technical bar. Google Play's target API level requirement states that from 31 August 2026, “New apps and app updates must target Android 16 (API level 36) or higher to be submitted to Google Play,” with existing apps needing to target Android 15 (API level 35) or higher to stay available to new users on devices running a newer OS than the app targets, and an extension route to 1 November 2026 available through Play Console. Whatever you build with, it needs to be keeping up with that.

Not legal adviceThis is a plain reading of published policy on the date shown, not legal or professional advice, and policies change. Read Google's current text yourself before you submit, and take your own advice on anything that turns on your specific circumstances. Nothing here can promise a particular review outcome — that decision is Google's.

None of this affects building or previewing an app for your own site, and it does not affect distributing an APK outside the Play Store at all. It matters at the moment you decide to list.

Sources: Google Play Console Help — Spam and Android Developers — Meet Google Play's target API level requirement, both checked 26 Aug 2026.

How to check whether your website works inside an Android WebView

In the order that finds problems soonest, so you are not debugging a payment flow on top of a broken asset load.

  1. Run the checker on your live public URLPaste the address a stranger would type, not a localhost or staging URL behind a password. The checker fetches the page from a server, so anything reachable only from your own machine or your own network returns an error rather than a report.
  2. Fix transport before anything elseServe the page over HTTPS and remove hard-coded http:// asset URLs from themes, ad tags and analytics snippets. Cleartext support is disabled by default for apps targeting Android 9 and above, and a WebView in an app targeting Android 5.0 or later defaults to refusing insecure subresources on a secure page. Every other test is unreliable until this is clean.
  3. Open the site in a real WebView and inspect itLoad your URL in an Android WebView on a device or emulator, then attach Chrome DevTools over USB from chrome://inspect on your computer. Watch the console and the network panel while you use the site. Silently dropped subresources and blocked cookies show up here and nowhere else. One caveat that wastes an afternoon if you meet it cold: Android's guide states that your app's WebView will not enable connections from Chrome DevTools by default, and debugging has to be switched on in the app's own code — so an inspectable build is something the wrapper has to give you.
  4. Test the whole thing signed out, as a strangerThis is the step almost everyone skips. Your own phone already holds a session cookie, so you never see the sign-in screen that a new user hits first. A WebView keeps its own cookie jar and does not share logins with the browser, so clear the app data and create a fresh account end to end.
  5. Walk the money path on a real deviceIf the site takes payment, complete one real transaction inside the WebView, including any 3-D Secure challenge and any handoff to a bank or wallet app. Card sandboxes rarely reproduce the redirect chain and the custom-scheme handoffs that actually break checkouts inside an app.
  6. Build and preview free, then decidePaste the same URL into Free App Maker to build and preview the app. Building and previewing are free; downloading the finished signed APK is a one-time unlock, priced by country and always shown before checkout. Use the preview to confirm the fixes held before you commit to distributing anything.

Source: Android Developers — Debug WebViews with Chrome DevTools, checked 26 Aug 2026.

Six things people get wrong about WebView compatibility

1. “X-Frame-Options will blank my app”

The most repeated piece of WebView folklore, and mostly wrong. MDN defines the header as one that “can be used to indicate whether a browser should be allowed to render the document in a <frame>, <iframe>, <embed> or <object>” — that is, in a framing context. A WebView loading your URL renders it as the top-level document, so the header does not govern that load. It still matters when a part of your page is framed content from another origin, and it is a useful hint that the origin restricts embedding generally, which is why the checker reports it.

2. “It works in Chrome on my phone, so it works in the app”

Different cookie jar, different permission grants, different defaults for JavaScript, DOM storage, mixed content and third-party cookies. Chrome is the most misleading device you can test on, because it is the one environment guaranteed to have everything already configured.

3. “SameSite=None fixes third-party cookies”

It is necessary and not sufficient. The attribute makes the cookie eligible to be sent cross-site; the WebView's own default still refuses to accept it. Two independent gates, and web developers only control one of them.

4. “Service workers don't work in a WebView”

They do, and have since Android 7.0 — Android ships a controller class specifically to manage them. The thing that genuinely does not work is web push. Getting these two backwards leads people to rip out a working offline cache and keep shipping push code that will never fire.

5. “target="_blank" links just do nothing”

They do something, and it is worse than nothing: with the documented default they become top-level navigations that replace the current page. The user does not get a tab they can close, they get your app parked on a terms page or a third-party site. The genuine do-nothing failure is the other one — window.open() called without a user gesture, which is documented to fail silently.

6. “It passed the checker, so everything works”

A checker sees one HTTP response from a server. It cannot log in, tap a button, open a camera or complete a payment. Passing means nothing in the response will obviously break a WebView — which is exactly the right moment to build the app and go and look, not a substitute for looking.

Sources: MDN — X-Frame-Options and Android Developers — WebSettings, both checked 26 Aug 2026.

Where this fits in building the app

Compatibility is the first question, not the only one. If the checks come back clean, the next things you need are a package name, an icon set and a privacy policy for the listing. All of these are free to use, with no account:

These tool pages are free with no catch — no account, no watermark, nothing held back. On the main website to APK converter, building and previewing your app is free too; downloading the finished signed APK is a one-time unlock, priced by country and always shown to you before checkout.

FAQ

WebView compatibility questions

What is an Android WebView app?
A WebView app is an Android application that loads your website inside a native Android shell using the WebView component — essentially a chromeless browser built into the app. It runs the same Chromium engine as Chrome, but it is a separate sandbox: Android's own documentation describes a WebView as not sharing cookies or logins with the user's main browser. This is how tools like Free App Maker work: your website URL is wrapped in a signed APK.
Does X-Frame-Options stop my site loading in a WebView?
Usually not, and this is the most common misconception about WebView compatibility. X-Frame-Options tells a browser whether it may render your document inside a frame, iframe, embed or object element. A WebView loading your URL renders it as the top-level page, not as a frame, so the header does not apply to that navigation. It still matters in two situations: when part of your page is itself framed content from another origin, and when the same server or CDN rule that sets the header also blocks unfamiliar user agents. The checker reports the header so you can tell which situation you are in.
Does Sign in with Google work inside a WebView app?
No — Google blocks it. Google's OAuth 2.0 policies state that a developer must not direct a Google OAuth 2.0 authorization request to an embedded user-agent under the developer's control, and an attempt returns a disallowed_useragent error instead of a sign-in screen. Android's own guidance is to send third-party sign-in flows to Custom Tabs or the system browser, where the browser handles the credentials. If Google is the only way to create an account on your site, add an email sign-in path before you wrap it, or new users will stop at the login screen.
Do passkeys work in an Android WebView?
Only if the app opts in. Passkeys in a WebView go through Android's Credential Manager, which Android's guide says is supported natively in the android.webkit.WebView library in version 1.12.0 and later. The app also has to check for the WEB_AUTHENTICATION feature and call setWebAuthenticationSupport(), and it must be associated with your site using digital asset linking. None of that is something your web page can trigger on its own, so keep a password or emailed-link route open for app users until you have tested passkey sign-in on a real device.
Do third-party cookies work in an Android WebView?
Not by default. Android's CookieManager documentation states that apps targeting Android 5.0 Lollipop or later default to disallowing third-party cookies, and the app has to switch them on for each WebView instance. First-party cookies are accepted by default. Setting SameSite=None with Secure on your cookies does not change this: that attribute is what makes a cross-site cookie legal for a browser to send, not permission for the WebView to accept it.
Will my checkout and 3-D Secure work in a WebView?
A hosted checkout that completes as an ordinary top-level navigation usually works, because a WebView follows the redirect to the bank's challenge page and back. Two things break it. A wrapper that pushes every off-domain URL out to the system browser drops the customer out of the app mid-payment and never receives the return. And a bank or wallet handoff that uses a custom scheme or Android's intent syntax has no handler inside a bare WebView, so the button does nothing unless the app intercepts it. Test with a real card on a real device before you launch.
Do camera, microphone and location work in a WebView?
They can, but three separate things have to line up. The app must declare the matching Android permission, the user must grant it at the runtime prompt Android shows for dangerous permissions such as camera and microphone, and the app must answer the WebView callback that passes the grant through to your page. Android's documentation is explicit for location: geolocation is enabled by default in WebSettings, but the app also needs a location permission and must implement the onGeolocationPermissionsShowPrompt callback. On Android 7.0 and later, geolocation requests from non-secure origins are denied automatically.
Does file upload work in a WebView?
Only if the app implements it. Android's documentation for the onShowFileChooser callback is blunt: the default behaviour is that WebView will cancel all file requests. So a file input renders, the user taps it, and nothing happens unless the wrapper handles the chooser. Downloads are the same story from the other side — a WebView does not save files by itself, and the app has to register a download listener for content the rendering engine cannot display.
Do service workers work in an Android WebView?
Yes, and this one surprises people. Android added ServiceWorkerController in API level 24 (Android 7.0) to manage service workers used by WebView, so an offline cache written with a service worker generally works. Web push is the part that does not: MDN's compatibility data lists PushManager and ServiceWorkerRegistration.showNotification as unsupported in Android WebView. If your app needs notifications, they have to come from a native channel rather than from your web push code.
Will the PWA install prompt appear in my app?
No, and it should not. Installing a progressive web app is a browser affordance — it lives in the browser's own interface, which a WebView does not have. Someone using your Android app has already installed it, so an add-to-home-screen banner is dead weight in that context. Hide it for your app's user agent. If you specifically want browser-grade PWA behaviour on Android, Google's route for that is a Trusted Web Activity, where the content is rendered by the user's own browser rather than by an embedded WebView.
Do target="_blank" links open a new window in a WebView app?
No, and the documented behaviour is not what most people expect. Support for multiple windows is off by default, and Android's reference states that when it is disabled, requests to open new windows from window.open() or from links with target="_blank" are treated as top-level navigations, replacing the current page in the same WebView. So the link takes over your app instead of opening a tab the user can close. Separately, window.open() called without a user gesture is documented to fail and do nothing.
Do tel: and mailto: links work in a WebView app?
It depends on the app. Android's WebViewClient reference notes that if no WebViewClient is provided, WebView asks Activity Manager to choose the proper handler for the URL — but nearly every wrapper does provide one in order to control navigation, and that removes the default. The same reference warns that calling loadUrl with a non-HTTP(S) URL will fail. So a phone or email link works only if the wrapper recognises the scheme and fires the matching Android intent. Test the actual buttons in the actual app.
Will my background video autoplay in a WebView app?
Not by default. Android documents setMediaPlaybackRequiresUserGesture with a default of true, meaning a WebView requires a user gesture before it plays media. Autoplaying hero videos and muted background loops sit on their poster frame until somebody taps, so give them a real poster image and a visible play control. Fullscreen playback is app-side too: Android hands it to the app through WebChromeClient.onShowCustomView, and a wrapper that does not implement that callback leaves the fullscreen button showing a black view.
Can I publish a WebView app of my website on Google Play?
Google Play's Spam policy says it does not allow apps whose primary purpose is to drive affiliate traffic to a website or provide a webview of a website without permission from the website owner or administrator. The qualifier matters: wrapping a site you own or run is not what that clause prohibits, while wrapping somebody else's is. The same policy also restricts repetitive apps that merely provide the same experience as apps already on Google Play. This is a plain reading of published policy on the date shown rather than legal advice, and review outcomes are Google's decision — read the current policy yourself before you submit.
My site failed the check — what do I do?
Each failed check shows a plain-language reason. The most common fixes: (1) Serve the page over HTTPS and remove any http:// asset URLs left in your theme, ad tags or analytics snippets. (2) Add a viewport meta tag with width=device-width, initial-scale=1 to your HTML. (3) Make the first screen reachable without a login. (4) Improve load speed with a CDN or image compression. Then run the check again.
Does checking my site store any data?
No. The checker fetches your URL to inspect HTTP headers and page content, then discards the result. We do not store URLs or results. The check is anonymous.
My site passed all checks — can I build my Android app now?
A passing score means nothing in the server response will obviously break a WebView, which is the right moment to build and look at the real thing. It is not a promise that every feature works, because the checker only ever sees one HTTP response — it cannot log in, tap your checkout or ask for your camera. Paste the same URL into Free App Maker, build and preview for free, then walk your own critical path inside the app.

Site passed? Build your app now.

Paste the same URL into Free App Maker and your signed Android APK is ready in 60 seconds.

Convert to Android — Free →