# mdn/browser-compat-data: the JSON dataset behind MDN's compatibility tables

> BCD is a machine-readable dataset of browser support for Web APIs, CSS, HTML, JavaScript and more, published as the @mdn/browser-compat-data npm package and consumed by MDN Web Docs, CanIUse and several IDEs. It answers support questions programmatically, but it does not test browsers for you.

**mdn/browser-compat-data** — Browser compatibility data for Web technologies as displayed on MDN

- Repository: https://github.com/mdn/browser-compat-data
- Website: https://developer.mozilla.org
- Stars: 5,760 · Forks: 2,645
- Language: JSON
- License: CC0-1.0
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/mdn-browser-compat-data

## What mdn/browser-compat-data actually is, and who needs it

BCD is a dataset, not a checker. The README describes it as machine-readable compatibility data for Web technologies such as Web APIs, JavaScript features and CSS properties, with the stated goal of helping developers write cross-browser compatible sites. The consumers named in the README are MDN Web Docs, CanIUse, Visual Studio Code and WebStorm.

That consumer list is the clearest signal of the intended audience. BCD is for people building tools that need to know, for a given feature and a given browser, whether support exists and from which version. If you are writing a linter that flags a CSS property against a browser support target, generating documentation tables, or building an editor hint, this is the data layer. If you want to know whether the browser currently open on a user's machine supports something, BCD is the wrong shape entirely: it is a static snapshot, not a runtime probe.

The dataset is large. The README states there are over 15,000 features, and it explicitly warns that apart from the documented top-level objects, feature-level support data may change at any time. That sentence should govern how you depend on it.

## The tree layout: top-level objects and __compat leaves

The package is a tree of objects. Support and browser data objects sit at the leaves, and the README's usage example reaches one through ordinary property access. The top-level keys correspond to web platform areas: api, browsers, css, html, http, javascript, manifests, mathml, mediatypes, svg, webassembly, webdriver and webextensions, plus a __meta object holding the package version and the timestamp of when that version was built.

Within those, the structure follows the platform. css splits into at-rules, properties, selectors and types. html splits into elements and global_attributes. http splits into headers, methods and status. javascript splits into builtins, classes, functions, grammar, operators and statements. webextensions and webdriver have their own sub-trees, with webdriver split into bidi and classic.

The leaf convention is the part worth internalising: a feature's compatibility record lives under a __compat key. The README's first example reads bcd.css.properties.background.__compat, and its second shows that bracket syntax works identically: bcd['api']['Document']['body']['__compat']. The definitive description of the format is not the README at all. It is the schema definitions under schemas/, and the README says so directly. Treat the schemas directory as the specification and the README as a tour.

## Installing @mdn/browser-compat-data and reading your first support statement

The npm package is the standard route. The README gives npm and yarn installs, and package.json pins the engine requirement to node >=24, with npm 11.8.0 or newer expected as the dev package manager. If you are on an older Node line, that engines field is the first thing to check.

```bash
npm install @mdn/browser-compat-data
```

Once installed, import it. The README shows several import forms because the package ships JSON and the syntax for importing JSON has shifted across Node versions. For Node 20 and later, the import-attributes form is the one documented first:

```js
import bcd from '@mdn/browser-compat-data' with { type: 'json' };

const support = bcd.css.properties.background.__compat;
console.log(support);
```

What you get back is a compat data object following the schema, not a boolean. The README does not spell out its fields in the sections shown here; the schema definitions do. So the honest first step after printing that object is to open schemas/ and read which keys you are looking at before you write branching logic against it.

For older Node versions the README offers the ESM wrapper, which avoids the JSON import syntax question altogether:

```js
import bcd from '@mdn/browser-compat-data/forLegacyNode';
```

CommonJS works too, with no import syntax concerns: `const bcd = require('@mdn/browser-compat-data');`. If you are not in Node at all, the README documents a CDN path for Deno and browsers via unpkg, and a raw data.json file in releases for other languages. That last option matters: the dataset is language-agnostic JSON, so a Python or Go service can consume the same file without the npm package.

## TypeScript types and the semantic versioning promise

BCD exports TypeScript type definitions, and package.json shows they are generated from the schema definitions rather than hand-written. The exports map is explicit about this: the require condition points types at ./build/require.d.ts and the import condition at ./build/import.d.mts, with a separate ./types subpath exposing ./build/types.d.ts. If you are writing a typed consumer, that means the shape of a compat object is available to you at compile time, which is a meaningful difference from a plain JSON blob you have to cast.

The versioning policy is the part to read carefully before you build on it. The README points to a Semantic versioning policy section and states that, apart from the explicitly documented objects, feature-level support data may change at any time. Read that as a deliberate boundary: the top-level object names are the stable contract, the contents of individual feature records are not. A patch or minor release can change a support statement for a feature you depend on, because the underlying truth about browsers changed.

For a tool that regenerates output on every release, that is fine. For a system that caches BCD-derived answers and diffs them, it means you need your own change detection on top of the package, because the package version number will not tell you which features moved.

## Where BCD stops being the right tool

The failure mode is conceptual, not technical. BCD records what browsers support, and it is consumed by MDN and CanIUse to render tables. It does not execute anything. If your question is "does this specific browser build, with these flags, on this device, support this API", BCD cannot answer it. It has no runtime, no feature-detection helper, and no per-device data. The README's own framing is documentation of compatibility, not verification of it.

There is a second limit. The README notes that apart from the documented top-level objects, feature-level support data may change at any time. If your product's correctness depends on a specific support statement being stable across releases, you have picked a dependency that explicitly declines to guarantee that. Pin the version and diff the data yourself, or accept that your output can shift under you.

A third: the dataset is broad across web platform areas, but it is still a curated record. The README describes mediatypes support in terms of whether an image type displays correctly in an img src or as a CSS background-image. That is a definitional choice baked into the data, and any definitional choice will not match every consumer's question. Where your definition of support differs from the project's, you are reading someone else's answer, not measuring your own.

## BCD against runtime feature detection

The natural alternative is runtime feature detection, the pattern where you test for a capability in the browser itself rather than consulting a table. The difference in approach is fundamental. Runtime detection answers for the one browser in front of you, right now, including flags, polyfill state and vendor quirks. BCD answers for a documented population of browsers and versions, offline, at build time.

That makes them complements, not substitutes, and the choice is dictated by where your code runs. A build step that warns a developer that a CSS property is unsupported in a target browser cannot use runtime detection, because there is no browser in the build. A page deciding whether to call an API should not ship the whole dataset to make that decision, because the dataset is a large JSON tree and the browser can answer the question directly.

BCD's advantage is coverage of the matrix: every browser and version the project tracks, in one file, with a schema and generated TypeScript types. Runtime detection's advantage is truth about the actual environment. If you find yourself pulling BCD into client-side code to decide what to render, that is usually a sign the question belongs at build time or in a linter instead.

## Licence, maintenance and what an upgrade costs you

The package is licensed CC0-1.0, stated in package.json and confirmed by the LICENSE file at the repository root. CC0 is a public domain dedication rather than a permissive software licence, which is unusual for an npm package and worth flagging to whoever reviews dependencies in your organisation. The repository also carries SECURITY.md, GOVERNANCE.md and CODE_OF_CONDUCT.md, so the project has documented its governance rather than leaving it implicit. None of this is legal advice; if the distinction between CC0 and an MIT-style licence matters to your legal team, that is their call to make.

On maintenance: the last push to the default branch was on 2026-09-22, and the recent release list shows v8.1.2 on 2026-09-17, v8.1.1 on 2026-09-10 and a next tag published on 2026-09-22. The repository is not archived. The release cadence visible here is roughly weekly for patch releases, with a continuously published next tag.

The upgrade cost is not in the install. It is in the diff. Because feature-level data may change between releases, an upgrade can alter your tool's output without any API change. The repository ships RELEASE_NOTES.md and a release_notes/ directory, which is where you look to understand what moved. Budget for reading those, or for running your own comparison of the data.json between two versions, rather than assuming a version bump is inert.

## Conclusion

Adopt BCD if you need programmatic browser support data for tooling, linting or documentation, and you can pin a release and handle its data shape. Do not adopt it if you need live feature detection in a running page, or if you want a runtime library that hides the schema from you. Before committing, check the schema definitions under schemas/ for the fields you plan to read, and confirm the semantic versioning policy in the README against your upgrade cadence, because feature-level support data may change at any time.

## FAQ

### How can I check browser compatibility using mdn/browser-compat-data?

Import the package, then read the __compat object for the feature you care about, for example bcd.css.properties.background.__compat. The returned object follows the schema definitions under schemas/, which the README calls the definitive description of the format.

### What should I do if my browser isn't compatible?

BCD does not answer this, because it is a static dataset rather than a runtime check. It records which browsers and versions support a given feature, and the README states its goal is to help developers write cross-browser compatible sites using that data.

### What is a compatible browser according to mdn/browser-compat-data?

There is no single definition in the dataset. Support is recorded per feature and per browser version, and for some areas the project applies its own definition, such as treating an image type as supported when it displays correctly in an img src or as a CSS background-image.

### Can mdn/browser-compat-data tell me if my browser is outdated?

No. BCD contains no runtime or per-device data, so it cannot inspect the browser you are using. It documents support statements for browsers and JavaScript runtimes as a tree of JSON objects.

## Sources

- [License: CC0-1.0](https://github.com/mdn/browser-compat-data/blob/main/LICENSE)
- [mdn/browser-compat-data on GitHub](https://github.com/mdn/browser-compat-data)
- [Project website](https://developer.mozilla.org)
- [README](https://github.com/mdn/browser-compat-data/blob/main/README.md)
- [Releases](https://github.com/mdn/browser-compat-data/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/mdn-browser-compat-data
