To debug an HTML APK without a computer, add a small script at the top of index.html that catches window.onerror, unhandled promise rejections and console.error and prints them in an overlay on the page. Rebuild, reproduce the problem, read the error, fix it, then remove the script before release.
Key takeaways
- Release WebView apps cannot be inspected with chrome://inspect.
- Catch errors as early as possible — the debug script must be the first script.
- Most blank screens are a missing file: log failed resource loads too.
- Remove the overlay (or hide it behind a gesture) before you publish.
Why you can't just open DevTools
Remote debugging of a WebView works only when the app turns it on, and release builds normally leave it off for security. So the console messages that would explain a problem go nowhere. The fix is to make your page report its own errors.
The on-screen console
Generate a configured version with the on-screen error console tool, or paste this as the very first thing in <head>:
<script>
(function () {
var box, q = [];
function out(kind, msg) {
var line = '[' + kind + '] ' + msg;
if (!document.body) { q.push(line); return; }
if (!box) {
box = document.createElement('pre');
box.style.cssText = 'position:fixed;left:0;right:0;bottom:0;max-height:40vh;overflow:auto;margin:0;' +
'padding:8px;background:rgba(20,0,0,.92);color:#ffd7d7;font:12px/1.4 monospace;z-index:2147483647;white-space:pre-wrap';
box.onclick = function () { box.remove(); box = null; };
document.body.appendChild(box);
}
box.textContent += line + '\n';
}
window.addEventListener('error', function (e) {
if (e.target && e.target !== window) out('load', (e.target.src || e.target.href) + ' failed');
else out('error', e.message + ' @ ' + (e.filename || '').split('/').pop() + ':' + e.lineno);
}, true);
window.addEventListener('unhandledrejection', function (e) { out('promise', e.reason && (e.reason.stack || e.reason)); });
var ce = console.error; console.error = function () { out('console', [].join.call(arguments, ' ')); ce.apply(console, arguments); };
document.addEventListener('DOMContentLoaded', function () { q.forEach(function (l) { out('', l); }); q = []; });
})();
</script>The capture-phase error listener also catches failed loads of scripts, stylesheets and images — the cause of most blank screens.
Blank-screen triage
| Overlay shows | Likely cause | Fix |
|---|---|---|
[load] …/app.js failed | Wrong or absolute path, or wrong file-name case | Make paths relative; match case exactly |
Unexpected token '<' | A script path returns an HTML page | The file is missing from the ZIP |
X is not defined | A library from a CDN did not load offline | Bundle the library locally |
Failed to fetch | API unreachable or CORS blocked | Allow the app origin on your API |
| Nothing at all, still blank | JS ran but rendered nothing (router found no route) | Use hash routing; log the route on start |
Leave yourself breadcrumbs
Add console.error('reached step 3', state) at key points while debugging — the overlay shows those too. For data, JSON.stringify(obj).slice(0, 500) keeps it readable.
If you do have a computer
Reproduce the app's environment by serving your files from a /web/ sub-folder over http and opening them with DevTools' device mode — the paths behave as they will inside the app. That catches most problems before you build.
Before release
Remove the script, or gate it: show the overlay only after five quick taps on your logo, so testers can still reach it.
Frequently asked questions
Can I use chrome://inspect on my APK?
Only if the app enables WebView debugging, which release builds normally do not. Use an on-screen error console in the page instead.
Why is my HTML APK just a white screen?
Most often a file failed to load (absolute path, wrong case, missing from the ZIP) or a CDN library is unavailable offline. An on-screen console shows which.