Skip to content

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.

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);
}

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);
}

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.

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 [];
}
}
  • Feature-detect with 'queryLocalFonts' in window before 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 a SecurityError.
  • Catch NotAllowedError for 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 postscriptNames filter when you only need to check for specific fonts (for example, ones a document already embeds by name).