npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

airtable-ofetch

v0.1.4

Published

JS Client for Airtable Web API built on top @unjs/ofetch

Readme

airtable-ofetch

npm codecov License: MIT jsDocs.io

Modern JS client for Airtable Web API

🚀 Quick Start

Install:

pnpm install airtable-ofetch

Import:

// CommonJS
const { Airtable } = require('airtable-ofetch');
// ESM / TypeScript
import { Airtable } from 'airtable-ofetch';

const airtable = new Airtable(); // Will read process.env.AIRTABLE_API_KEY

✔️ Works on node, browser, and workers

This client is implemented on top of unjs/ofetch to provide better cross-runtime compatibility.

🔧 Configuration

You can provide custom configuration during client initialization:

const airtable = new Airtable({
  /**
   * As of February 1st 2024, Airtable Web API has ended deprecation period
   * of Airtable API Key and has prompted all users to migrate to use personal
   * access token (PAT) or OAuth access token
   *
   * @see https://airtable.com/developers/web/api/authentication
   */
  apiKey: 'YOUR_PERSONAL_ACCESS_TOKEN', // Otherwise default to process.env.AIRTABLE_API_KEY

  /**
   * API Endpoint URL target, users may override this if they need
   * to pass requests through an API proxy. Don't include trailing slash
   * for consistency.
   *
   * @optional
   */
  endpointURL: 'https://api.airtable.internal', // Also configurable via AIRTABLE_ENDPOINT_URL

  /**
   * Content Endpoint URL target, users may override this if they need
   * to pass requests through an API proxy. Don't include trailing slash
   * for consistency.
   *
   * @see https://airtable.com/developers/web/api/upload-attachment
   * @optional
   */
  contentEndpointURL: 'https://content.airtable.internal', // Also configurable via AIRTABLE_CONTENT_ENDPOINT_URL

  /**
   * How long in ms before aborting a request attempt.
   * Default to 5 minutes.
   *
   * @optional
   */
  requestTimeout: 180 * 1000,

  /**
   * Disable / configure exponential backoff with jitter retry
   * whenever API request receive 429 status code response
   *
   * @see https://airtable.com/developers/web/api/rate-limits
   * @optional
   */
  noRetryIfRateLimited: true, // This disable retry

  /**
   * Disable automatic reset when server response with Iteration Timeout error
   * when calling `.all()` on List Records query
   *
   * @see {@link https://airtable.com/developers/web/api/list-records#:~:text=LIST_RECORDS_ITERATOR_NOT_AVAILABLE}
   * @optional
   */
  noIterationReset: true, // Throws when iteration timeout

  /**
   * Custom headers to be included when requesting to API endpoint
   *
   * @optional
   */
  customHeaders: {
    'X-Custom-Header': 'Custom Value',
  }
})

You can customize maximum retries and its backoff behavior:

const airtable = new Airtable({
  noRetryIfRateLimited: {
    maxRetries: 5, // Maximum retry attempts. Default to Infinity
    initialDelayMs: 500, // Initial retry delay in ms. Default to 1000ms
    maxDelayMs: 2000, // Maximum retry delay in ms. Default to 45_000ms
  },
})

You can create a new client that inherit previous configuration and replace some of it:

const airtable = new Airtable({ apiKey: 'custom-api-key' });

// New client will inherit manually passed apiKey
const newAirtable = airtable.create({ customHeaders: { 'X-Custom-Header': 'Custom Value' } });

🔁 Pagination

This client implement similar pagination control as airtable.js using eachPage() that you can control whenever possible:

const table = new Airtable().base('appEpvhkjHcG8OvKu').table('tblc7ieWKVQM9eequ');

// List records endpoint exposes pagination
// https://airtable.com/developers/web/api/list-records
const query = table.list({ pageSize: 50 });

// Async callback is supported
await query.eachPage(async (records: AirtableRecord[]) => {
  // Do something with records
  console.log(records);
  // Return false to stop pagination early, otherwise pagination will continue until all records are exhausted
  return false;
});

[!NOTE] eachPage() API need you to handle Iteration Timeout scenario yourself

For convenient usage, you also have firstPage() or all() method:

const table = new Airtable().base('appEpvhkjHcG8OvKu').table('tblc7ieWKVQM9eequ');

// List comments also exposes pagination
// https://airtable.com/developers/web/api/list-comments
const query = table.comments('recPaibwSLDbZr80V', { pageSize: 50 });

const firstPageComments: AirtableComment[] = await query.firstPage();
const allComments: AirtableComment[] = await query.all();

Some endpoint doesn't expose pagination control, in this case we always return all records:

const airtable = new Airtable();

// It uses pagination but doesn't provide much control
// https://airtable.com/developers/web/api/list-bases
const bases: BaseInfo[] = await airtable.bases();

📘 Type Friendly

Specify your own data:

import { Airtable, type FieldSet } from "airtable-ofetch";

interface TableData extends FieldSet {
  Name: string;
  Notes: string;
}

// Type-assisted table
const table = new Airtable().base('appEpvhkjHcG8OvKu').table<TableData>('tblc7ieWKVQM9eequ');

// Return typed records
const records: AirtableRecord<TableData>[] = await table.list().all();
console.log(records[0].get('Name')) // Field name will be type assisted

Consult here to see interface shape. Adjusted in accordance to Web API docs.

📦 Bundler Notes

Since this client implemented on top of unjs/ofetch, please consult ofetch's Bundler Notes to ensure compatibility with your project.

💻 Development

  • Clone this repository
  • Enable Corepack using corepack enable
  • Install dependencies using pnpm install
  • Run interactive tests using pnpm dev

License

MIT