Fix & optimise

What works offline in a ZIP-to-APK app

Everything in the ZIP is inside the APK, so the app works with no connection. But bundled pages have no web origin, and a handful of browser features behave differently because of it. Here is the full list — what works, what does not, and the workaround for each.

7 min read Updated September 2026

Quick answer: HTML, CSS, images, fonts, classic JavaScript, canvas, audio, video, localStorage, IndexedDB, forms, links between pages and back navigation all work offline in a ZIP-to-APK app. Four things do not, because bundled pages load from file:// with no origin: <script type="module">, fetch()/XHR of local files, service workers, and cookies. Each has a simple workaround.

Why the origin matters

A web page served from https://example.com has an origin, and browsers use the origin to decide what the page may read, store and request. Files in an APK are loaded from the app's bundle, which the WebView treats like file://: a page with a null origin. Nearly everything still works, because nearly everything is origin-agnostic. The exceptions are the features whose security model is built entirely on origins.

Works exactly as on the web

FeatureNotes
HTML, CSS, images, SVG, fontsRelative paths. WOFF2 and WebP supported.
Classic <script src> and inline scriptsAny JavaScript Chrome runs. ES2020+ syntax is fine; only the module loading is blocked.
Links between bundled pagesabout.html, ../index.html, anchors, the back button.
localStorage, sessionStoragePersisted in the app's private data. Shared between all your pages.
IndexedDBWorks; suitable for large offline datasets.
Canvas, WebGL, Web AudioGames and visualisations run at Chrome speed.
<audio>, <video>From bundled files. Autoplay-with-sound needs a user gesture, as in Chrome.
Forms, validation, <input type=file>File picker opens the Android chooser. Submission needs JavaScript — there is no server.
CSS animations, transitions, media queriesIncluding prefers-color-scheme and safe-area insets.
Requests to https:// APIsWork when online, subject to the API's CORS headers (a null origin is sent as Origin: null).
window.open, mailto:, tel:Hand off to the system.

Does not work, and the workaround

Module scripts

<script type="module"> is fetched with CORS, and a null origin fails the check — blank page. Workaround: bundle to a classic script (IIFE) and load it with <script src>. Every bundler does this; hand-written modules can be concatenated.

fetch() and XMLHttpRequest of local files

Chrome forbids a file:// page from reading other file:// URLs via XHR/fetch. Workaround: ship data as JavaScript — data.js with window.DATA = […] — and load it as a script. For text content, a <template> element or a hidden <script type="text/plain"> block. Requests to https:// endpoints are unaffected.

Service workers

Require a secure origin; registration throws on file://. Workaround: none needed — the app is already offline. Guard the registration so it does not throw: if (location.protocol.startsWith('http')) navigator.serviceWorker.register(…).

Cookies

Cookies are keyed by origin, and a null origin has nowhere to keep them. Workaround: use localStorage, which works.

History-mode routing

history.pushState('/about') works, but a reload or deep link to /about has no server to answer it. Workaround: hash routing (#/about).

Web Share, clipboard, notifications

navigator.share and navigator.clipboard require a secure context and may be unavailable; Notification is not supported in a WebView. Workaround: feature-detect and fall back; for push, use the builder's Pro push feature, which is native.

Storage limits

The WebView allows a generous quota — typically a percentage of free device storage, hundreds of megabytes on any modern phone. localStorage is capped at about 5 MB per origin as in Chrome; IndexedDB is the place for anything larger. Storage is wiped when the app is uninstalled and preserved across updates as long as the package name and signing key stay the same.

Testing offline behaviour

On your computer, open index.html from disk (file://) in Chrome: every limitation above appears there too, with errors in the console. On the phone, enable aeroplane mode and open the app; anything that still relied on the network will show up. The ZIP checker lists external hosts a page loads from, so you can see what depends on a connection before you build.

Questions people ask

Does localStorage persist between app launches?

Yes. The WebView keeps localStorage and IndexedDB in the app's private storage. They survive restarts and reboots and are removed when the app is uninstalled.

Can the app open external links in the phone's browser?

Yes. Links to https:// addresses open in the WebView by default; the builder can be set to hand external domains to the system browser instead.

Can I play audio and video offline?

Yes, from files in the ZIP. Autoplay with sound is blocked until the user taps something, exactly as in Chrome.

Does geolocation work?

With the location permission enabled in the builder (Pro), navigator.geolocation works as on the web. On the free tier the permission is not requested and the call fails.

Read next

Ready to turn your ZIP into an APK?

Upload the ZIP of your HTML project, pick a name and an icon, and download a signed Android APK. Free, in the browser, no Android Studio.

Convert ZIP to APK