urltoapp.dev
Learn

How a URL app works, layer by layer

Knowing what sits between your website and the screen explains almost every bug you'll ever see in a URL app — and how to fix it from the website side.

Updated Oct 20262 min readurltoapp.dev

Short answer

A URL app is a native Android activity hosting an Android System WebView. The WebView renders your site with Chromium, keeps its own cookie jar and local storage, identifies itself with a user agent containing ; wv), and hands certain events — file pickers, new windows, downloads, permission requests, non-web links — to native code. Whether those events work depends on how the converter wrote that native code.

Layer 1: the Android app shell

The shell is a small Kotlin or Java app with an AndroidManifest.xml (name, package, permissions, which screens exist), one main activity and resources such as icons and the splash screen. It decides the app's identity and which Android permissions it can even ask for — no camera permission in the manifest means no camera, whatever your site does.

Layer 2: the WebView and its settings

The WebView is not a browser. Out of the box it has JavaScript turned off, no local storage, no file chooser and no pop-up windows. A good converter switches on what real sites need:

  • javaScriptEnabled and domStorageEnabled — most modern sites break without them.
  • Third-party cookies — off by default in WebViews, needed by many embedded payment and login widgets.
  • Multiple-window support — so target="_blank" and window.open() don't silently do nothing.
  • Mixed content — WebViews refuse http resources on https pages. Fix the site rather than loosening this.

Layer 3: the bridges

When a page needs something only Android can do, the WebView asks the app: show a file chooser, grant geolocation, open a new window, download a file, handle a tel: or intent: link. Each needs native code. If a feature “works in Chrome but not in the app”, a missing bridge is the first suspect — see uploads and camera and external links.

Cookies and storage are the app's own

The app doesn't share cookies with Chrome. A user logged in to your site in Chrome is logged out in the app the first time; after that, the app's cookies persist like a browser's. Clearing the app's storage in Android settings logs them out. This is also why “Sign in with Google” can't reuse the Chrome session — and why Google blocks it outright in WebViews.

The user agent tells your site it's inside the app

WebView user agents include ; wv) and usually Version/4.0. Converters may append their own token too. Your site can use that to hide “download our app” banners, footers or cookie notices that make no sense inside the app. The app mode snippet generator writes the JavaScript and CSS for you.

Layer 4: signing

The finished package is signed with a private key. Android refuses to install an update signed by a different key, and Google Play keeps your app's identity tied to it. Losing the key means you can no longer update the app. With Play App Signing, Google holds the final key and you sign uploads with an upload key, which can be reset if lost.

Who updates what

PartUpdated byHow often
Your website contentYou, on your serverAny time — users see it at once
WebView engineGoogle, via PlayRoughly monthly
App shell (name, icon, features)You, with a rebuildWhen you need to

FAQ

Is a WebView the same as Chrome?

It uses the same Chromium engine, but it's a component embedded in your app, with its own settings, storage and no browser UI. Some Chrome features (like Google sign-in or web push) aren't available in it.

Why does my site look different in the app?

Usually a cached old version, a cookie banner shown again because cookies are separate, or a missing setting like DOM storage. Pull to refresh, then check the console with Chrome's remote debugging.

Can my website know it's running inside the app?

Yes, from the user agent (; wv)) or a query parameter you add to the start URL. Use the app mode snippet.

Read next