Library / SDK
contentful/contentful.js avatar
contentful/contentful.js

contentful.js: a Delivery API client built around chainable queries

JavaScript library for Contentful's Delivery API (node & browser)

1,296 stars211 forksTypeScriptMIT

At a glance

What is it?
contentful.js is the MIT licensed JavaScript and TypeScript client for Contentful's Delivery and Preview APIs, built as an ES module with CommonJS and browser bundles alongside, and its distinguishing feature is a chainable query builder with built-in rate limiting. The client requires Node 18 or newer and targets a fixed set of browsers.
Who is it for?
contentful.js is the right choice for a JavaScript or TypeScript project reading structured content from a Contentful space, because the chainable query builder, the built-in rate limit handling and the shipped type declarations remove most of the boilerplate a hand-written REST client would need, and the MIT licence keeps adoption simple; it is the wrong choice if your content does not live in Contentful or if you need the Management API rather than the read-only Delivery and Preview APIs, and before you ship you should check that the browserslist targets in package.json, which include Chrome 75, Edge 74, Firefox 73 and Safari 13, still match the browsers your users actually have.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 21, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the client covers, and what it deliberately leaves out

contentful.js is the JavaScript library for Contentful's Content Delivery API and Content Preview API, and the project states its purpose plainly: it helps you access your content stored in Contentful with your JavaScript applications. The package description is shorter still, describing itself as a client for Contentful's Content Delivery API.

The feature list is specific about scope. Content retrieval through the Delivery API and the Preview API, synchronization, localization support, link resolution, built-in rate limiting with recovery procedures, and support for Environments, which was added in version 6.0.0. There is no mention of a Management API client, so writes to a space are out of scope for this package.

The two APIs it does cover serve different purposes, and the distinction matters for how you configure it. The Delivery API serves published content, which is what a production site reads. The Preview API serves draft content for editorial review, which is what a preview environment or a content editor's screen should read. The library covers both, so the difference is a configuration choice rather than a different package.

The package also describes itself as built to integrate with the modern software stack rather than to be a traditional CMS, offering a central hub for structured content, management and delivery APIs, and a customizable web app. The client is the piece a developer touches, and it exposes that structured content as typed objects rather than as a page-rendering API.

Installing, importing, and the three build shapes

Installation is one command:

bash
npm install contentful

The import style depends on your environment, and the library ships three distinct builds to cover the cases. In a modern environment the ESM import is the intended path:

js
import * as contentful from 'contentful'

The package declares `"type": "module"` in package.json, and the project explains the reasoning: to ensure compatibility across various JavaScript environments, the library is built as an ECMAScript Module by default. A CommonJS bundle is offered for environments that do not support ESM, and a separate bundle is available for direct usage within browsers.

The package.json exports map makes the arrangement concrete. The root export resolves types to the generated declarations, import to the ESM build, and require to the CJS build, with the ESM path also listed as main. The files array publishes dist, images and a set of markdown documents including MIGRATION.md, TYPESCRIPT.md and ADVANCED.md, so the migration and TypeScript guides ship with the package and are readable straight from node_modules.

That last detail is a small sign of a mature package. Documentation that is installed alongside the code is documentation that stays in step with the version you actually depend on, rather than a site that has moved on to the next major release.

The chain modifier is the API you will actually use

The table of contents lists client chain modifiers under three headings, Entries, Assets and Sync, and this is the part of the library that differs most from a generic REST wrapper. Instead of writing query parameters by hand, you chain methods onto a client call.

The pattern is that a request starts from a client method, then modifiers narrow it. A typical sequence filters entries by content type, constrains the fields you want back, adds an include to resolve links, applies a limit, and orders the result, with the resolved entities then read off the result. The same chaining works on assets and on the sync endpoint, and the Sync variant in particular is a single call that returns a token and a set of changed entities, which is the basis for keeping a local cache in step with the space.

This design has a practical effect on application code. Rather than a scattered set of query string parameters that drift out of sync with each other, the modifiers are composed in one expression, and the type of the result reflects what you asked for. For a TypeScript project, that is the difference between an untyped blob of JSON and something the compiler can check.

The library also resolves links, which matters for anyone modelling content with references between entries. Without resolution you get a bare link object; with it you get the target entry inlined, at the cost of having to think about the include depth your request asks for.

Rate limiting with recovery, and the cursor pagination model

Two operational behaviours are built into the client and are worth understanding before you write request code.

The first is rate limiting. The feature list describes built-in rate limiting with recovery procedures, which means the client handles the API's throttling responses rather than leaving you to write a retry loop. The API returns a rate limit reset window, and a client that ignores it will see bursts of failed requests the moment you query a large space from several pages at once. Handling this at the library level means a page of your application does not have to know about it.

The second is cursor-based pagination, which has its own section in the documentation. Cursor pagination is a different model from numbered pages, and the difference is not cosmetic. With cursor pagination, a result set that changes between requests can be walked without skipping or repeating items, because the client follows a cursor rather than a page number. The cost is that the cursor is opaque, so a user interface that wants to jump to page 12 cannot compute the offset, and a design that assumes numbered pages has to change.

Both of these are the kind of detail that a thin wrapper gets wrong and that you would otherwise discover in production. The library handles them, and the project documents them as first-class topics rather than as caveats.

Browser support, Node version, and the build pipeline behind them

The supported environments are listed explicitly: Chrome, Firefox, Edge, Safari, Node.js on LTS, and React Native with the Metro bundler. The minimum browser versions are not repeated in the prose, and the project points to the package.json for them, where the browserslist field lists Chrome 75 or newer, Edge 74 or newer, Firefox 73 or newer, Safari 13 or newer, and a general greater than 0.3 percent target. The engines field requires Node 18 or newer.

Those numbers are the real compatibility contract, and they are worth checking against your own analytics rather than assuming. A library that supports Safari 13 will use features that were available in a 2019 browser, which constrains what the internals can do even if your own users are all on a newer release.

The build is Rollup on top of TypeScript, and the scripts make the output matrix explicit. The build runs a clean, then the ESM compile with tsc, then the Rollup bundles in production mode. A separate check script verifies each artifact against a target: es-check runs against the ESM modules, the CJS bundle, and both the plain and minified browser bundles, with es2017 for the module and CommonJS outputs and es2018 for the browser ones. That check is a deliberate guard, since a bundler can happily emit syntax that breaks an older target.

The tooling around it is modern and automated: semantic-release determines the version, which is why the package.json version field reads 0.0.0-determined-by-semantic-release, Renovate is configured for dependency updates, Husky handles git hooks, and Vitest with a setup file and a config file runs the tests. Type definitions ship as generated declarations from the TypeScript compile, typedoc builds the API documentation from typedoc.json, and a separate esdoc.json sits in the repository, suggesting a second documentation pipeline.

TypeScript support, environments, and the file layout

TypeScript is a first-class concern rather than an afterthought. The package publishes generated declarations at the types entry of its exports map, and there is a dedicated TYPESCRIPT.md document that ships with the package, plus a tsd configuration that points the type tests at test/types with the lib directory as the root, which is how the type definitions are verified against real usage.

Content Environments are supported since version 6.0.0. The documentation links Environments to a concept page on multiple environments, and the client can be pointed at a specific environment. This is a substantial feature for teams that run a staging content set alongside production, and it is the kind of thing that is much easier to adopt at the start of a project than to retrofit.

The repository layout is worth a glance because it shows how the project is organised. The library sources live in lib/, the build is driven by rollup.config.js and tsconfig files, tests are in test/, and there is a docs/ directory alongside several top-level documents: ADVANCED.md for deeper topics, MIGRATION.md, TYPESCRIPT.md, DOCS.md, CONTRIBUTING.md, an ARCHITECTURE.md, and an AGENTS.md. There is also a .contentful/ directory, an esdoc.json, a .bito/ directory with a .bito.yaml configuration, and a catalog-info.yaml, which is a Backstage service catalogue descriptor.

That Backstage descriptor is a small but telling detail: it means the package is registered as a service in the catalogue of the organisation that maintains it, and its ownership and documentation metadata are managed as part of an internal platform rather than as an afterthought.

Maintenance, licensing, and the upgrade path

The repository is not archived, and the last push was on 2026-10-06. The release history shows a steady patch cadence inside a single major version, with v11.12.10 on 2026-09-09 and v11.12.9 and v11.12.8 both on 2026-08-06. Three releases across the major line within a few months, and no major bump, is the pattern of a library that has settled into maintenance mode for its current API shape.

That has implications for adoption. A stable major version means the entry points described in the documentation, the chain modifiers and the exports map, are not going to move under you. It also means the interesting changes happen in the Contentful platform itself, in how the Delivery API behaves, rather than in the shape of this client.

The licence is MIT, with a LICENSE file in the repository and the badge matching. A permissive licence is the right default for a client library, since it lets you ship it inside a closed-source application as long as you keep the copyright notice, and the client carries no runtime obligations of its own beyond needing a space and its credentials.

For the upgrade path, the practical file is MIGRATION.md, which ships with the package. The project also points to a Contentful community Slack for questions, and asks bug reports and feature proposals to go through the issue tracker, with a separate route for sharing confidential information. What is not present is a published deprecation policy, so a team planning a long-lived integration should treat the major version as stable but keep an eye on the migration guide rather than assuming none will be needed.

Editorial conclusion

contentful.js is the right choice for a JavaScript or TypeScript project reading structured content from a Contentful space, because the chainable query builder, the built-in rate limit handling and the shipped type declarations remove most of the boilerplate a hand-written REST client would need, and the MIT licence keeps adoption simple; it is the wrong choice if your content does not live in Contentful or if you need the Management API rather than the read-only Delivery and Preview APIs, and before you ship you should check that the browserslist targets in package.json, which include Chrome 75, Edge 74, Firefox 73 and Safari 13, still match the browsers your users actually have.

Frequently asked questions

How do I install contentful.js?

Run npm install contentful. The library is built as an ES module by default with the type module declaration in package.json, so a modern environment imports it as import * as contentful from 'contentful', while a CommonJS environment uses require('contentful').

Does contentful.js support TypeScript?

Yes. Type declarations are generated and published at the types entry of the package exports map, a TYPESCRIPT.md document ships with the package, and tsd is configured against test/types to verify the definitions against real usage.

Which Node.js and browser versions does contentful.js support?

The engines field requires Node 18 or newer, and the browserslist field lists Chrome 75, Edge 74, Firefox 73, Safari 13 and a general greater than 0.3 percent target. React Native with the Metro bundler is also listed as supported.

Can contentful.js read draft content for previews?

Yes. The library covers both the Content Delivery API, which serves published content, and the Content Preview API, which serves draft content, and the choice between them is a configuration setting rather than a different package.

How does contentful.js handle API rate limits?

Rate limiting is built into the client with recovery procedures, so the library handles throttling responses instead of leaving the application to write its own retry loop.

Official sources

  1. contentful/contentful.js on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/contentful-contentful-js.svg)](https://hysenlabs.com/projects/contentful-contentful-js)