How to Fix navigator.share is Undefined in Chrome
This guide is part of Understanding Secure Context Requirements, which itself is part of Web Share API & Security Contexts.
When navigator.share is undefined in Chrome, the browser is withholding the API due to a security context violation, an iframe sandbox restriction, or a platform limitation. This guide provides a focused diagnostic workflow: run a detection gate first, isolate the root cause second, then deploy the correct fix or fallback.
Feature Detection Gate
Before calling navigator.share, always run this gate. A loose truthy check (if (navigator.share)) is not sufficient — the property may be present but not callable in some environments. Type-checking eliminates the ambiguity:
export function isShareSupported() {
return (
window.isSecureContext === true &&
typeof navigator.share === 'function'
);
}
Call isShareSupported() before rendering your share button and again before invoking the API. If either condition fails, route immediately to the fallback rather than attempting the call.
Solution Walkthrough
Step 1 — Confirm the Secure Context
Open DevTools Console on the page where navigator.share is undefined and run:
console.log(window.isSecureContext); // must be true
console.log(location.protocol); // must be "https:" or page on localhost
If isSecureContext is false, the browser will not expose the Web Share API regardless of Chrome version. For local development, Chrome automatically grants secure-context status to localhost, 127.0.0.1, and ::1 — no certificate needed. For staging environments on a LAN IP (e.g. 192.168.x.x), you must serve over HTTPS. The step-by-step guide to testing the Web Share API on localhost covers mkcert and Vite/webpack HTTPS proxy configuration.
Step 2 — Enforce Strict Feature Detection Before Invocation
Replace every loose check in your codebase with the strict form, and validate payload support with navigator.canShare() before passing files:
export async function triggerShare(data) {
if (!window.isSecureContext || typeof navigator.share !== 'function') {
return activateFallback(data);
}
const payload = { title: data.title, text: data.text, url: data.url };
if (data.file instanceof File) {
const filePayload = { files: [data.file] };
if (typeof navigator.canShare === 'function' && !navigator.canShare(filePayload)) {
return activateFallback(data);
}
payload.files = [data.file];
}
try {
await navigator.share(payload);
} catch (err) {
if (err.name === 'AbortError') return; // user dismissed — not an error
activateFallback(data);
}
}
The canShare() pre-flight prevents a DataError on platforms that do not support the specific file MIME type you are sharing.
Step 3 — Fix iframe Sandbox Restrictions
If your share button lives inside an iframe (common in embedded widgets or third-party comment systems), the iframe must explicitly grant the web-share permission. Without it, the API is stripped from the browsing context even if the parent page is on HTTPS:
<!-- Cross-origin iframe: grant web-share permission explicitly -->
<iframe
src="https://widget.example.com/share-button"
allow="web-share"
sandbox="allow-scripts allow-same-origin allow-forms"
></iframe>
If you cannot modify the iframe element (e.g. it is rendered by a third-party embed), move the share invocation logic to the parent window and use postMessage to relay the share request from the iframe.
Step 4 — Wire the Clipboard Fallback
When native sharing is unavailable, copy the URL to the clipboard. This covers desktop Chrome on older OSes (pre-Chrome 89), Firefox (which has limited Web Share API support), and any environment failing the secure-context check:
async function activateFallback(data) {
const textToCopy = data.url ?? data.text ?? data.title ?? '';
if (typeof navigator.clipboard?.writeText === 'function') {
try {
await navigator.clipboard.writeText(textToCopy);
showToast('Link copied to clipboard');
return;
} catch {
// clipboard denied — fall through to SMS/email fallback
}
}
// Last resort: SMS URI or mailto for cross-device sharing
const smsUri = `sms:?body=${encodeURIComponent(textToCopy)}`;
window.location.href = smsUri;
}
For a more comprehensive fallback chain — including QR code generation and SMS/email fallback architectures — see the permission flows and progressive enhancement section.
Failure Modes and Recovery
| Symptom | Root Cause | Fix |
|---|---|---|
navigator.share is undefined |
window.isSecureContext is false |
Switch to HTTPS; use localhost for dev |
navigator.share is undefined (secure page) |
Desktop Chrome < 89, Firefox, or enterprise policy | Strict feature-detect + clipboard fallback |
navigator.share present but undefined in iframe |
Missing allow="web-share" on iframe element |
Add the allow attribute or use postMessage |
NotAllowedError on invocation |
Called outside a direct user gesture (e.g. from setTimeout) |
Invoke synchronously in a click handler |
DataError on file share |
File MIME type not supported on this platform | Pre-validate with navigator.canShare({ files }) |
AbortError |
User dismissed the share sheet | Catch and do nothing — this is expected behaviour |
Memory leak pattern: constructing a Blob, calling URL.createObjectURL(), and then failing to call URL.revokeObjectURL() after the share promise settles will accumulate heap allocations. Always revoke in a finally block.
Browser and Platform Caveat
Desktop Chrome has supported the Web Share API since version 89 (March 2021) on Windows, macOS, and ChromeOS. Linux desktop Chrome exposes navigator.share but the native share sheet is limited — it may open the system clipboard or an OS-level dialog depending on the desktop environment. Safari on macOS has supported the API since Safari 15. Firefox does not support navigator.share on any platform as of mid-2026; your fallback will always activate on Firefox. The browser support matrix for the Web Share API lists exact minimum versions and known gaps per platform.
FAQ
Why does navigator.share return undefined on desktop Chrome?
navigator.share has been available in Chrome for desktop since version 89. If you see undefined on a modern desktop Chrome, the most likely cause is an insecure context (window.isSecureContext is false) or an iframe sandbox restriction. Run console.log(window.isSecureContext) in DevTools to confirm the context before investigating other causes.
Can I use navigator.share inside a cross-origin iframe?
No, not without explicit permission. Cross-origin iframes are blocked from invoking the Web Share API by default. Add allow="web-share" to the <iframe> element, or relay the share request from the iframe to the parent window via postMessage and invoke navigator.share there.
Is HTTPS strictly required for local development testing?
No. Chrome treats localhost, 127.0.0.1, and ::1 as secure contexts automatically. You only need a TLS certificate when testing on a LAN IP or physical device not routing through localhost. Verify with window.isSecureContext in DevTools before troubleshooting anything else.
How do I handle large file payloads without crashing the browser?
Call navigator.canShare({ files: [yourFile] }) before invoking navigator.share. iOS typically accepts up to 10–50 MB per file depending on the target app; Android and Chromium allow up to ~50 MB. Pass File objects — not bare Blob instances — to the files array, since some platforms require the name property that File carries. Always revoke any object URLs in a finally block.