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
The server must return a 200 OK. A 401, 403, or 5xx means users will see an error screen inside the app.
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.
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.
Without <meta name="viewport">, the page renders at desktop width inside the app and appears tiny.
If the first screen requires a login, users who haven't created an account will hit a wall immediately on open.
Pages over 4 seconds feel broken on a mobile network. The app should load in under 2 seconds for a good first impression.
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:
- Your users start logged out. Somebody who is signed in to your site in Chrome on the same phone opens your app and sees a login screen. Nothing is broken; the app simply has its own cookie jar.
- Browser conveniences are gone. No shared autofill, no saved passwords, no saved payment methods and addresses — Android lists all of those as things Custom Tabs bring and a WebView does not.
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.
| Capability | In a WebView | The short reason |
|---|---|---|
| HTTPS pages | Works | The normal case. Cleartext HTTP is the one that needs an opt-in. |
| Mixed content on an HTTPS page | Blocked | Apps targeting Android 5.0+ default to MIXED_CONTENT_NEVER_ALLOW. |
| First-party cookies | Works | setAcceptCookie is true by default. |
| Third-party cookies | Off by default | Apps targeting Android 5.0+ default to disallowing them. |
| Sign in with Google | Blocked by Google | Google's OAuth policy forbids embedded user-agents. |
| Card payment redirects and 3-D Secure | Usually works | Top-level redirects are fine; app handoffs and iframe challenges are not. |
| Camera and microphone | Partly | Needs a manifest permission, a runtime grant and a WebView callback. |
| Geolocation | Partly | Same chain, plus HTTPS-only from Android 7.0. |
| File upload fields | Partly | WebView cancels every file request unless the app implements the chooser. |
| Passkeys and WebAuthn | Partly | Needs AndroidX WebKit 1.12.0+, digital asset linking and an app-side opt-in. |
target="_blank" and window.open | Changes meaning | Treated as a top-level navigation that replaces the current page, by default. |
tel:, mailto:, intent: links | Partly | Once the app sets a WebViewClient, routing them becomes the app's job. |
| Video autoplay | Needs a gesture | setMediaPlaybackRequiresUserGesture defaults to true. |
| Service workers and offline cache | Works | Managed by ServiceWorkerController since Android 7.0. |
| Web push notifications | Not supported | PushManager and showNotification are unsupported in WebView. |
| PWA install prompt | No surface | Installing 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:
- A CMS theme or page builder that stored absolute
http://URLs in the database when the site was first migrated to HTTPS. - An ad tag, affiliate pixel or old analytics snippet pasted in years ago.
- A third-party embed — a map, a review widget, a chat bubble — whose provider still serves one asset insecurely.
- User-generated content: forum posts and product descriptions full of
http://image links.
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.
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.
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:
- 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.
- 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.
- 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.
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:
- The app is built against a recent enough AndroidX WebKit and Credential Manager.
- The app checks
WebViewFeature.isFeatureSupported(WebViewFeature.WEB_AUTHENTICATION)and then callsWebSettingsCompat.setWebAuthenticationSupport(). Nothing happens without that call. - The app is associated with your site by digital asset linking — Android's guide says you “will also need to associate your app with a website that your app owns using digital asset linking.”
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.
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.
- The app declares the permission. Nothing the web page does can conjure a permission the APK never asked for.
- 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.
- 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 asWebChromeClient.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”) andRESOURCE_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.”
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:
- A “Terms” or “Privacy” link in your footer swallows the whole app. The user's only way back is the device back gesture — which works only if the wrapper wired the back button to the WebView's history rather than to closing the activity.
- A social or “share on” link loads a third-party site inside your app frame, with your app's name at the top of the task switcher and no address bar to tell the user where they are.
- A document or report preview that opened in a tab on the web now leaves the app parked on a file the WebView may not even be able to render.
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.
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.
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.
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.
- 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.
- 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. - 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://inspecton 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. - 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.
- 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.
- 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
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 →