Skip to content

Node module & API

Add the package to a project:

Terminal window
npm install google-font-cli

The entry point is CommonJS:

const GoogleFontList = require("google-font-cli");

There is no separate named export; the module itself is the GoogleFontList constructor.


const fontList = new GoogleFontList();

Creating a list starts loading the catalog asynchronously (load(false) is invoked from the constructor). Until loading finishes, fontList.data may still be empty. In your own code, await fontList.load() before searching or reading data. Pass true to force a network fetch and ignore a valid cache (same idea as CLI --refresh-cache).

load returns Promise<{ fromCache: boolean }>. The fromCache flag tells you whether the list came from ~/.gfcli/cache.json.

NameMeaning
dataArray of GoogleFont instances after the list is populated.
MethodMeaning
load(forceRefresh?)Load from cache (if valid and forceRefresh is falsy) or download from https://gwfh.mranftl.com/api/fonts, then populate data. Returns a promise; concurrent calls share the same in-flight promise.
downloadList()Download the raw catalog from the network, parse JSON, write cache, populate. Returns Promise<{ fromCache: false }> (or rejects). Used inside load when cache misses.
populate(fontArray)Replace data with GoogleFont instances built from an array of plain GWFH-style objects. Emits success.

All of the following use callbacks (err, filteredList) where filteredList is a new GoogleFontList instance whose data is the subset. They read from the current fontList.data, so finish await fontList.load() before calling them.

MethodBehavior
searchFont(term, field, callback)Case-insensitive: every whitespace-separated token in term must appear as a substring of el[field] (e.g. family). Word order does not matter.
searchFontByName(term, callback)Same as searchFont(term, 'family', callback).
searchFontByType(term, callback)Same as searchFont(term, 'category', callback).
getFont(term, field, callback)Exact match of term to el[field] (case-insensitive).
getFontByName(term, callback)getFont(term, 'family', callback).
getFontByType(term, callback)getFont(term, 'category', callback).

Helper utilities on a list instance:

MethodReturns
getFirst()First GoogleFont in data, or false if empty.
isSingle()true if data.length === 1.
forEachFont(fn, callback?)Calls fn(font, index) for each entry; optional callback() when done (synchronous loop).
clone()Returns a new GoogleFontList and assigns this list’s data array to it (used for filtered results).

GoogleFontList inherits Node’s EventEmitter.

EventWhen
successEmitted with the list instance when populate runs successfully (including after a downloaded JSON parse).
errorEmitted when parseRawData cannot parse JSON or the payload is not an array of fonts.

New code should still await load() rather than relying only on events.


Each element of fontList.data is an instance of the internal GoogleFont class (constructed from GWFH list entries).

The constructor **Object.assign**s the raw font record, then sets:

  • family: from familyName or family
  • category, variants: as on the source object (variants may be an array of ids or a map)
  • apiUrl: https://gwfh.mranftl.com/api/fonts/{slug} with slug from the family name

Prefer getters below over reading raw fields when you can.

MethodReturns
getFamily()Family name string.
getCategory()Category string or undefined.
getVariants()Array of variant ids (keys if variants was an object).
getCssUrl()https://fonts.googleapis.com/css?family=... with spaces as +.
MethodMeaning
_getFileMapAsync(format)format: 'ttf' | 'woff2'. Fetches this.apiUrl, parses variant entries, returns Promise<Record<variantId, url>> (only variants that exist for that format).
_getFileMap(format?, callback?)Callback or Promise form; see source for overloads.
MethodMeaning
saveAtAsync(variants, destFolder, format)variants: array of ids, or falsy to mean “all keys from the file map”. format: 'ttf' | 'woff2'. Resolves to FontResult[]. If some variants fail to save, throws AggregateError; check err.results for partial FontResult[].
saveAt(variants, destFolder, format?, callback?)Callback style; supports legacy (variants, destFolder, callback) with default format TTF.

Each FontResult: { family, variant, path }.

MethodMeaning
installAsync(variants)Downloads TTF only (internal format is fixed to TTF). variants array or falsy for all. Promise<FontResult[]>.
install(variants, callback)Callback wrapper around installAsync.

Internally, weights are normalized (e.g. 400 / normalregular, 400italic / normalitalicitalic). Other ids are lowercased and trimmed.


const GoogleFontList = require("google-font-cli");
async function main() {
const fontList = new GoogleFontList();
await fontList.load();
fontList.searchFontByName("Source Sans Pro", (err, filtered) => {
if (err) throw err;
const font = filtered.getFirst();
if (!font) return;
font.saveAtAsync(["300", "400"], "./fonts", "ttf").then((results) => {
results.forEach((r) => console.log(r.variant, r.path));
});
});
}
main().catch(console.error);
const GoogleFontList = require("google-font-cli");
function getFontByNameAsync(list, name) {
return new Promise((resolve, reject) => {
list.getFontByName(name, (err, filtered) =>
err ? reject(err) : resolve(filtered)
);
});
}
(async () => {
const fontList = new GoogleFontList();
await fontList.load();
const filtered = await getFontByNameAsync(fontList, "Inter");
if (!filtered.isSingle()) {
console.log("Ambiguous or missing");
return;
}
const inter = filtered.getFirst();
const installed = await inter.installAsync(["regular", "700"]);
console.log(installed);
})();
const GoogleFontList = require("google-font-cli");
const fontList = new GoogleFontList();
fontList.once("error", (err) => {
console.error(err);
});
fontList.once("success", () => {
fontList.searchFontByName("Roboto", (err, filtered) => {
if (err) throw err;
filtered.getFirst().install(false, (e, results) => {
if (e) throw e;
console.log(results);
});
});
});

Note: with load()-driven flows, success may have fired before you attach listeners; await fontList.load() avoids that race.