https://github.com/fontsource/google-font-metadata
A metadata generator that fetches and parses the Google Fonts API.
https://github.com/fontsource/google-font-metadata
fonts fontsource google-font google-fonts google-fonts-api metadata metadata-generator unicode-range
Last synced: 8 months ago
JSON representation
A metadata generator that fetches and parses the Google Fonts API.
- Host: GitHub
- URL: https://github.com/fontsource/google-font-metadata
- Owner: fontsource
- License: mit
- Created: 2020-07-14T12:27:33.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2025-06-01T01:29:58.000Z (10 months ago)
- Last Synced: 2025-07-22T15:30:53.555Z (8 months ago)
- Topics: fonts, fontsource, google-font, google-fonts, google-fonts-api, metadata, metadata-generator, unicode-range
- Language: TypeScript
- Homepage:
- Size: 54.1 MB
- Stars: 38
- Watchers: 2
- Forks: 11
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Google Font Metadata
[](https://badge.fury.io/js/google-font-metadata) [](https://github.com/fontsource/google-font-metadata/blob/master/LICENSE) [](https://github.com/fontsource/google-font-metadata/stargazers)
A metadata generator that fetches and parses the Google Fonts API to be primarily used for the [Fontsource monorepo](https://github.com/fontsource/fontsource).
## Installation
Install the package from `npm`:
```shell
npm install google-font-metadata
```
## Usage
The project exports the following data:
```ts
import {
APIv1,
APIv2,
APIVariable,
APIIconStatic,
APIIconVariable,
APILicense,
APIRegistry,
} from "google-font-metadata";
const {
APIv1,
APIv2,
APIVariable,
APIIconStatic,
APIIconVariable,
APILicense,
APIRegistry,
} = require("google-font-metadata");
console.dir(APIv2);
```
## APIv1
Uses the Google Fonts CSS APIv1 that includes different font files for each subset, but does NOT include unicode-range values. This isn't usually recommended.
It exports [`data/google-fonts-v1.json`](https://github.com/fontsource/google-font-metadata/tree/main/data/google-fonts-v1.json).
```json
{
...
"abel": {
"family": "Abel",
"id": "abel",
"subsets": ["latin"],
"weights": [400],
"styles": ["normal"],
"variants": {
"400": {
"normal": {
"latin": {
"url": {
"woff2": "https://fonts.gstatic.com/s/abel/v18/MwQ5bhbm2POE2V9BPQ.woff2",
"woff": "https://fonts.gstatic.com/s/abel/v18/MwQ5bhbm2POE2V9BOw.woff",
"truetype": "https://fonts.gstatic.com/s/abel/v18/MwQ5bhbm2POE2V9BOA.ttf"
}
}
}
}
},
"defSubset": "latin",
"lastModified": "2022-04-20",
"version": "v18",
"category": "sans-serif"
},
...
}
```
## APIv2
Uses the Google Fonts CSS APIv2 and includes the unicode-range values for every subset. However, the API serves `ttf` files with **ALL** subsets included in one file and therefore all links for those file types in the same subset lead to the same link for each weight and style. `woff2` and `woff` files are individually split per subset.
Exports [`data/google-fonts-v2.json`](https://github.com/fontsource/google-font-metadata/tree/main/data/google-fonts-v2.json).
```json
{
...
"abel": {
"family": "Abel",
"id": "abel",
"subsets": ["latin"],
"weights": [400],
"styles": ["normal"],
"unicodeRange": {
"latin": "U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD"
},
"variants": {
"400": {
"normal": {
"latin": {
"url": {
"woff2": "https://fonts.gstatic.com/s/abel/v18/MwQ5bhbm2POE2V9BPQ.woff2",
"woff": "https://fonts.gstatic.com/s/abel/v18/MwQ5bhbm2POE6Vs.woff",
"truetype": "https://fonts.gstatic.com/s/abel/v18/MwQ5bhbm2POE6Vg.ttf"
}
}
}
}
},
"defSubset": "latin",
"lastModified": "2022-04-20",
"version": "v18",
"category": "sans-serif"
},
...
}
```
Note that fonts with large glyphsets such as the Japanese, Korean or Chinese language, are divided into many smaller **numbered** subsets that utilize the unicode-range @fontface selector. An example is Noto Sans JP which returns the following:
```json
{
...
"noto-sans-jp": {
"family": "Noto Sans JP",
"id": "noto-sans-jp",
"subsets": ["japanese", "latin"],
"weights": [100, 300, 400, 500, 700, 900],
"styles": ["normal"],
"unicodeRange": {
"[0]": "U+25ee8,...,U+2f9f4",
"[1]": "U+1f235-1f23b,...,U+25ed8",
...
"[119]": "U+20,...,U+ff0e"
},
"variants": {
"100": {
"normal": {
"[0]": {
"url": {
"woff2": "https://fonts.gstatic.com/s/notosansjp/v42/-F6ofjtqLzI2JPCgQBnw7HFQoggPkENvl4B0ZLgOquiXidBa3qHiDcp2RQ.0.woff2",
"woff": "https://fonts.gstatic.com/s/notosansjp/v42/-F62fjtqLzI2JPCgQBnw7HFoxQII2lcnk-AFfrgQrvWXpdFg3KXxAMsKMbdN.0.woff",
"opentype": "https://fonts.gstatic.com/s/notosansjp/v42/-F6ofjtqLzI2JPCgQBnw7HFQoggM.otf"
}
},
...,
},
...,
}
}
}
...
}
```
## APIVariable
Scrapes the Google Fonts directory and uses the Google Fonts API to generate all the relevant axis definitions and download variant metadata. You can learn more variable font axis' [here](https://fonts.google.com/variablefonts).
There are 3 default variants:
- `wght` - Only links to font files that only have the `wght` axis.
- `standard` - A default set of fonts that includes `wght, wdth, slnt, opsz` axis' if available.
- `full` - Links to font files that have all the axis' included within them.
Furthermore, a variant is generated for each unique axis in the font, e.g. if `wdth` exists, `variants.wdth.normal.latin` will exist. Note that the `wght` axis is also included in each unique custom variant.
Note that `standard` or `full` variants may not exist if there are no relevant axes in the font for that classification. This is to prevent duplicate variants with different names.
Exports [`data/variable.json`](https://github.com/fontsource/google-font-metadata/tree/main/data/variable.json).
```json
{
...
"akshar": {
"family": "Akshar",
"id": "akshar",
"axes": {
"wght": { "default": "400", "min": "300", "max": "700", "step": "1" }
},
"variants": {
"wght": {
"normal": {
"devanagari": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCpR5lhOc.woff2",
"latin-ext": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCqh5lhOc.woff2",
"latin": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCpB5l.woff2"
}
},
"full": {
"normal": {
"devanagari": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCpR5lhOc.woff2",
"latin-ext": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCqh5lhOc.woff2",
"latin": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCpB5l.woff2"
}
},
"standard": {
"normal": {
"devanagari": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCpR5lhOc.woff2",
"latin-ext": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCqh5lhOc.woff2",
"latin": "https://fonts.gstatic.com/s/akshar/v5/Yq6V-LyHWTfz9rGCpB5l.woff2"
}
}
}
},
...
}
```
Note that certain fonts such as Inter or Recursive have the SLNT axis, meaning their `font-style` in CSS won't be `normal` or `italic` on property `full` but `oblique x deg x deg`. Refer to the [CSS test fixture](https://github.com/fontsource/google-font-metadata/blob/v4/tests/fixtures/variable-parser/recursive-slnt-normal.css) for Recursive. While still showing as `normal` in metadata, it is up to the developer to include the `oblique` style if they are generating CSS using the `min` and `max` values from `recursive.axes.slnt` property.
### APIDirect and APIVariableDirect
These are arrays of generated objects from the `npx gfm generate [key]` command. It is unlikely you will use this.
```ts
import { APIDirect, APIVariableDirect } from "google-font-metadata";
const { APIDirect, APIVariableDirect } = require("google-font-metadata");
```
Exports [`data/api-response.json`](https://github.com/fontsource/google-font-metadata/tree/main/data/api-response.json) and [`data/variable-response.json`](https://github.com/fontsource/google-font-metadata/tree/main/data/variable-response.json) respectively.
## APILicense
Scrapes the [Google Fonts Attribution](https://fonts.google.com/attribution) page and returns a readable object.
```json
{
...
"abel": {
"id": "abel",
"authors": {
"copyright": "Copyright 2011, Matthew Desmond with Reserved Font Name Abel.",
"website": "http://www.madtype.com",
"email": "mattdesmond@gmail.com"
},
"license": {
"type": "SIL Open Font License, 1.1",
"url": "http://scripts.sil.org/OFL"
},
"original": "Copyright (c) 2011, Matthew Desmond (http://www.madtype.com | mattdesmond@gmail.com), with Reserved Font Name Abel."
},
...
}
```
Exports [`data/licenses.json`](https://github.com/fontsource/google-font-metadata/tree/main/data/licenses.json)
## APIRegistry
```json
{
...
{
"name": "Thick Stroke",
"tag": "XOPQ",
"min": -1000,
"max": 2000,
"default": 88,
"precision": 0
},
...
}
```
Exports [`data/axis-registry.json`](https://github.com/fontsource/google-font-metadata/tree/main/data/axis-registry.json)
You can refer to [`src/index.ts`](https://github.com/fontsource/google-font-metadata/blob/main/src/index.ts) and [`src/data.ts`](https://github.com/fontsource/google-font-metadata/blob/main/src/data.ts) to see all exports.
## Updating API Files
You can use the `gfm` CLI tool to update the metadata with fresh results from the Google APIs.
`npx gfm generate [key]` - Fetches the default Google Fonts API which can be used for parsing later. This has to be called before `npx gfm parse`.
Flags:
- `-n, --normal` - Only fetch the normal Google Developer API for APIv1 and APIv2.
- `-v, --variable` - Only scrape the variable axis page for APIVariable. Note `key` does not need to be given if this option is passed.
You are able to get a Google Fonts API `key` value from [here](https://console.developers.google.com/apis/credentials). Alternatively, you can use a `.env` file with `API_KEY=keyvalue` instead of providing a key argument in the command.
##
`npx gfm parse` - Parses through the Google Fonts CSS API and generate full metadata using the `generate` command data.
Flags:
- `-1, --v1` - Only parse and update APIv1.
- `-2, --v2` - Only parse and update APIv2.
- `-v, --variable` - Only parse and update APIVariable.
- `-l, --license` - Only parse and update APILicense.
- `-f, --force` - This skips the cache and force parses every font.
- `--no-validate` - This skips invoking `npx gfm validate` after finishing parsing.
##
`npx gfm validate` - Helper command to validate your existing metadata with a schema. This is automatically invoked with `npx gfm parse`.
Flags:
- `-1, --v1` - Only validate APIv1.
- `-2, --v2` - Only validate APIv2.
- `-v, --variable` - Only validate APIVariable.