# Local Font Access API: enumerating the fonts installed on a device

> How window.queryLocalFonts() lets a page enumerate locally installed fonts as FontData objects, the local-fonts permission it requires, why it does not need to return every font, and where it ships.

**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

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:

```js
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

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:

```js
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

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

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:

```js
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

- [ ] 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).

## Where to go next

- [File System Access API](/reference/capabilities/file-system-access/)
- [WebGPU](/reference/capabilities/webgpu/)