How to Query Local Fonts Using Font Access API
The Font Access API provides web applications with the ability to
discover and access the full catalog of locally installed fonts on a
user’s operating system. By utilizing the
window.queryLocalFonts() method in JavaScript, developers
can programmatically enumerate system fonts, inspect their metadata, and
retrieve raw binary font data. This guide explains the technical
workflow of the API, including permission management, font enumeration,
filtering options, and accessing raw SFNT font tables.
Security and Permission Requirements
Because enumerating local fonts can introduce fingerprinting risks, the Font Access API is restricted to secure contexts (HTTPS) and requires explicit user consent.
Before querying fonts, the browser prompts the user for permission. You can check or request permissions programmatically using the Permissions API:
const { state } = await navigator.permissions.query({ name: 'local-fonts' });
if (state === 'granted' || state === 'prompt') {
// Permission is either already granted or will trigger a prompt upon calling the API
}Enumerating All Local Fonts
The core method of the API is window.queryLocalFonts().
When called, it requests permission if not already granted and resolves
to an array of FontData objects representing the installed
fonts.
async function getInstalledFonts() {
try {
const availableFonts = await window.queryLocalFonts();
for (const font of availableFonts) {
console.log(`PostScript Name: ${font.postscriptName}`);
console.log(`Full Name: ${font.fullName}`);
console.log(`Family: ${font.family}`);
console.log(`Style: ${font.style}`);
}
} catch (err) {
console.error(`Error querying fonts: ${err.name}, ${err.message}`);
}
}Each FontData object exposes standard metadata
properties: * postscriptName: The unique identifier used to
target the font in PostScript contexts. * fullName: The
complete name of the font (e.g., “Helvetica Bold”). *
family: The overarching font family (e.g., “Helvetica”). *
style: The specific style variant (e.g., “Bold”,
“Italic”).
Filtering Specific Fonts
Querying the entire font registry can yield thousands of entries,
which can impact performance. If your application only requires specific
fonts, you can pass a postscriptNames filter to the query
method:
async function getSpecificFonts() {
const specificFonts = await window.queryLocalFonts({
postscriptNames: ["Verdana", "Verdana-Bold", "ArialMT"]
});
return specificFonts;
}Accessing Low-Level Binary Data
Beyond reading font metadata, advanced graphics and design tools
often require access to raw OpenType/TrueType tables. The
FontData object provides a blob() method that
returns a Promise resolving to a Blob
containing the complete font file:
async function parseFontTable(fontData) {
// Retrieve the binary SFNT data
const sfntBlob = await fontData.blob();
// Convert blob to ArrayBuffer for custom parsing or WebAssembly processing
const arrayBuffer = await sfntBlob.arrayBuffer();
return arrayBuffer;
}This binary access enables client-side rendering engines, layout engines, and WebAssembly modules to parse glyph data, OpenType features, and metrics directly within the browser without requiring external server-side font hosting.