Local Font Access support
Published Updated
The Local Font Access API’s window.queryLocalFonts() method returns a promise for
an array of FontData objects describing the fonts installed on a user’s device, gated
behind a local-fonts permission prompt.
Browser & ecosystem support
Section titled “Browser & ecosystem support”- Legend
- Yes
- Partial
- Flag
- No
- Unknown
| Browser / Platform | Support | Versions | Confidence | Source | Notes |
|---|---|---|---|---|---|
| Chrome (Desktop) | Yes | 103 | high | source | — |
| Chrome (Android) | No | — | high | source | 1 |
| Edge (Desktop) | Yes | 103 | high | source | 2 |
| Firefox (Desktop) | No | — | high | source | 3 |
| Firefox (Android) | No | — | high | source | 45 |
| Safari (macOS) | No | — | high | source | 6 |
| Safari (iOS) | No | — | high | source | 78 |
| Samsung Internet | No | — | high | source | 910 |
| WebView (Android) | No | — | high | source | 1112 |
- Implementation tracking: https://crbug.com/40840834.
- Derived by browser-compat-data mirroring from Chrome.
- No Firefox support is recorded in browser-compat-data.
- No Firefox for Android support is recorded in browser-compat-data.
- Derived by browser-compat-data mirroring from Firefox.
- No Safari support is recorded in browser-compat-data.
- No Safari on iOS support is recorded in browser-compat-data.
- Derived by browser-compat-data mirroring from Safari.
- Implementation tracking: https://crbug.com/40840834.
- Derived by browser-compat-data mirroring from Chrome Android.
- Implementation tracking: https://crbug.com/40840834.
- Derived by browser-compat-data mirroring from Chrome Android.
How to use it
Section titled “How to use it”queryLocalFonts() must be called from inside a user gesture handler (for example a
button’s click listener) — calling it at the top level of a script throws a
SecurityError. Paste this whole snippet into an HTML file and click the button to
exercise the real gesture-gated path:
<button id="choose-local-fonts">Choose local fonts</button><script> document.querySelector('#choose-local-fonts').addEventListener('click', async () => { const availableFonts = await window.queryLocalFonts(); for (const fontData of availableFonts) { console.log(fontData.postscriptName, fontData.fullName, fontData.family, fontData.style); } });</script>How to detect it at runtime
Section titled “How to detect it at runtime”Feature-detect queryLocalFonts before calling it, and fall back to a fixed list of
CSS generic font families when it is unavailable or the call fails:
// CSS generic families used when local font enumeration is unavailable.const BUNDLED_FONTS = ['system-ui', 'sans-serif', 'serif', 'monospace'];
async function listLocalFonts() { if (!('queryLocalFonts' in window)) { // Unsupported browser (Firefox, Safari, or older Chromium): local font // enumeration isn't available, so offer the generic-family fallback instead. return BUNDLED_FONTS; } try { const fonts = await window.queryLocalFonts(); return fonts.map((fontData) => fontData.fullName); } catch (err) { // Permission denied, or called without a user gesture: same fallback. return BUNDLED_FONTS; }}Practical checklist
Section titled “Practical checklist”- Firefox and Safari do not implement
queryLocalFonts()— per the table above, support is limited to Chromium desktop browsers, so always keep the generic-family fallback. queryLocalFonts()is only available in secure contexts and, per MDN, throws aSecurityErrorwhen called without prior user interaction or when a Permissions Policy blocks the feature; catchNotAllowedErrorseparately for a user-denied prompt.- Per MDN, the returned list is not guaranteed to be exhaustive or ordered like the filesystem — do not assume it reports every installed font.
Where to go next
Section titled “Where to go next”← Back to the Compatibility explorer.