Local Font Access API: enumerating the fonts installed on a device
Published Updated
In one line: the Local Font Access API’s window.queryLocalFonts() method returns a
promise for an array of FontData objects describing the fonts installed on the user’s
device, gated behind a local-fonts permission prompt.
Querying local fonts
Section titled “Querying local fonts”Per MDN, queryLocalFonts() takes an optional options object with a postscriptNames
array to scope the result to specific fonts; called with no arguments, it returns every
font the browser is willing to report:
const availableFonts = await window.queryLocalFonts();for (const fontData of availableFonts) { console.log(fontData.postscriptName, fontData.fullName, fontData.family, fontData.style);}What each FontData object holds
Section titled “What each FontData object holds”Per MDN’s FontData reference, each entry exposes four read-only string properties —
family, fullName, postscriptName, and style — plus a blob() method that resolves
to a Blob of the underlying SFNT font file’s raw bytes:
const [font] = await window.queryLocalFonts({ postscriptNames: ['Verdana-Bold'] });if (font) { const sfntBlob = await font.blob(); console.log(sfntBlob.size, sfntBlob.type);}Where it is supported
Section titled “Where it is supported”Per MDN, queryLocalFonts() is available only in secure contexts and is not Baseline
because it does not work in some of the most widely-used browsers — it ships in
Chromium-based desktop browsers (Chrome, Edge, and Opera), and Firefox and Safari do not
implement it.
Feature detection and fallback
Section titled “Feature detection and fallback”Per MDN, calling queryLocalFonts() without prior user interaction or when a Permissions
Policy blocks the feature throws a SecurityError, and a user-denied permission prompt
throws a NotAllowedError, so a caller needs both a support check and an error-handling
fallback:
async function listLocalFonts() { if (!('queryLocalFonts' in window)) { // Unsupported browser (Firefox, Safari, or older Chromium): fall back to the // site's own bundled/web-font list instead of a local enumeration. return []; } try { return await window.queryLocalFonts(); } catch (err) { // Permission denied, or called without a user gesture: same fallback. return []; }}Practical checklist
Section titled “Practical checklist”- Feature-detect with
'queryLocalFonts' in windowbefore calling it — Firefox and Safari do not implement the method at all. -
queryLocalFonts()is only available in secure contexts — feature-detect it accordingly. Once available, call it from within a user gesture: calling it without prior user interaction, or when a Permissions Policy blocks the feature, throws aSecurityError. - Catch
NotAllowedErrorfor a user-denied prompt and handle it like any other permission rejection, not a bug. - Per MDN, do not assume the returned list is exhaustive or ordered like the filesystem — the API is not required to report every installed font.
- Use the
postscriptNamesfilter when you only need to check for specific fonts (for example, ones a document already embeds by name).