Capabilities · API
Local Network Access: a local-request prompt
Published Updated
In one line: Local Network Access is a browser permission prompt, shown before a page running on the public internet is allowed to send a request to a device on the user’s local network (for example a router, printer, or local app server).
Why a prompt, not just a preflight
Section titled “Why a prompt, not just a preflight”The specification’s predecessor, Private Network Access, let a local device opt in to being contacted by sending a CORS preflight response header — no user in the loop at all. Per the explainer, that preflight-only model required changes to devices on the local network, whereas sites are far easier to update. Local Network Access replaces the PNA preflight gate with a browser-side permission prompt instead, shifting the burden to the public-origin website rather than to the local device. Per the specification, a user agent may persist this permission decision to reduce permission fatigue, but the exact scope of the grant — for example per origin, per device, or per network — is left implementation-defined.
How the prompt is triggered
Section titled “How the prompt is triggered”Per the Chrome for Developers blog, a public page’s own request to a local-network or loopback address is what triggers the prompt — a developer does not call a separate API to ask for the permission first:
// A page served from a public origin, fetching a device on the// user's local network (e.g. a router's status endpoint).const response = await fetch('http://192.168.1.1/status');Chrome began offering this behind a flag (chrome://flags/#local-network-access-check,
set to “Enabled (Blocking)”) from Chrome 138, and turned the prompt on by default in
Chrome 142. Per the Chrome blog, pages that rely on it must be served over a secure
context (HTTPS), must handle a denied prompt gracefully, and can use Permissions Policy to
delegate the access to an iframe.
Where it is supported
Section titled “Where it is supported”Per the Chrome for Developers blog, the Local Network Access prompt shipped by default in Chrome 142, after an opt-in testing period starting in Chrome 138. The specification is developed in the WICG and, per the explainer, some of its behaviour — such as whether cross-origin requests between two local-network origins are also gated — is left to each implementer’s discretion; the explainer states that Chromium currently only enforces the permission for requests from a public origin to a local or loopback address, not for local-to-local cross-origin requests.
Feature detection and fallback
Section titled “Feature detection and fallback”There is no dedicated “does this browser gate Local Network Access” call, but the
targetAddressSpace property on Request is part of the same effort and its presence is
a reasonable signal that the browser’s fetch stack understands local-network address
spaces at all. Check that alongside the secure-context requirement before attempting the
request, and treat any resulting failure generically — a rejected or throwing request can
mean an unsupported browser, an insecure context, a user-denied prompt, a CORS failure, or
simply an offline device, and (before Local Network Access shipped) a public page could
reach local addresses without any of this failing at all, so a failure must not be
attributed to a specific cause:
function supportsLocalNetworkAddressSpaces() { return typeof Request !== 'undefined' && 'targetAddressSpace' in Request.prototype;}
async function pingLocalDevice(url) { if (!window.isSecureContext || !supportsLocalNetworkAddressSpaces()) { // Either this browser doesn't expose the local-network address-space surface, // or the page isn't in a secure context, so the request cannot rely on it. return false; } try { const res = await fetch(url); return res.ok; } catch { // The request failed for an unknown reason (denied prompt, CORS, offline // device, or something else): fall back to asking the user to check the // device manually instead of retrying silently or guessing the cause. return false; }}Practical checklist
Section titled “Practical checklist”- Per the Chrome blog, the requesting page must run in a secure context (HTTPS) — local-network requests from an insecure page are not eligible for the prompt at all.
- Treat a denied or unsupported request as a normal, expected outcome: catch the failure and show the user a manual fallback rather than retrying the same request.
- Do not rely on a device’s old Private Network Access preflight opt-in header to bypass the prompt — Local Network Access replaced that server-side opt-in with a browser-side permission the local device cannot control.
- Per the explainer, Chromium does not currently gate local-to-local cross-origin requests the same way it gates public-to-local ones — do not assume every local-network request path is covered.
- If embedding local-network functionality in an iframe, delegate the permission explicitly with Permissions Policy rather than assuming it is inherited.
Where to go next
Section titled “Where to go next”Specifications
| Specification | Status |
|---|---|
| None. | |