How to export an entire Airtable base

Airtable exports one view at a time. How to get every table, the field setup, linked records and attachment files out of a base, by hand or with a script.

Updated

Airtable has no "export base" button. Downloads work one grid view at a time, as CSV, and include only what that view shows. A complete export of a base has four parts: every table's records, the links between them, the field setup, and the attachment files.

What a complete export needs

Part Why it matters CSV download API
Every record in every table The data itself One view per download Yes
Record IDs Rebuilding links and matching files to records No Yes
Linked records Relationships between tables As text of the linked record's primary field As record IDs
Field names and types Rebuilding the base No Yes, with the schema scope
Attachment files Your documents and images Links that expire after a few hours Links that expire after a few hours

The CSV route gets you readable tables. The API route gets you everything needed to rebuild the base accurately.

By hand: CSV downloads

For each table:

  1. Create a new grid view, or pick one with no filters and no hidden fields. Hidden fields are left out of the download and filters remove records.
  2. Open the view's menu (the arrow next to its name) and choose Download CSV.
  3. Rename the file after its table; Airtable names it after the view.

Then download the attachments separately, straight away, because the links in the CSVs stop working after a few hours. See how to download all attachments.

Finally, write down each field's type and options (single select choices, formulas, lookups, rollups). CSV files keep values, not field settings, and you'll need them to rebuild the base.

CSV download is available in the web and desktop apps, not on mobile. A base owner can block downloads from shared views.

With a script: JSON with record IDs

The Airtable Web API returns each table's field definitions and every record with its ID, with links between records as record IDs. This script saves schema.json and one JSON file per table.

  1. Create a personal access token with the data.records:read and schema.bases:read scopes and access to the base.
  2. Run it with Node.js 20 or later:
AIRTABLE_TOKEN=pat... node export-base.mjs appXXXXXXXXXXXXXX
// Saves the base's schema and every table's records as JSON in export-<base ID>/.
import { mkdir, writeFile } from "node:fs/promises";
import { join } from "node:path";

const [baseId] = process.argv.slice(2);
const headers = { Authorization: `Bearer ${process.env.AIRTABLE_TOKEN}` };
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

async function get(url) {
  while (true) {
    const response = await fetch(url, { headers });
    if (response.status === 429) {
      await sleep(30_000); // Airtable's rate limit asks for a 30-second pause.
      continue;
    }
    if (!response.ok) throw new Error(`Airtable answered ${response.status}`);
    await sleep(250); // Stay under 5 requests per second.
    return response.json();
  }
}

const folder = `export-${baseId}`;
await mkdir(folder, { recursive: true });

const { tables } = await get(`https://api.airtable.com/v0/meta/bases/${baseId}/tables`);
await writeFile(join(folder, "schema.json"), JSON.stringify(tables, null, 2));

for (const table of tables) {
  const records = [];
  let offset;

  do {
    const url = new URL(`https://api.airtable.com/v0/${baseId}/${table.id}`);
    url.searchParams.set("returnFieldsByFieldId", "true");
    if (offset) url.searchParams.set("offset", offset);

    const page = await get(url);
    records.push(...page.records);
    offset = page.offset;
  } while (offset);

  await writeFile(join(folder, `${table.id}.json`), JSON.stringify(records, null, 2));
  console.log(`${table.name}: ${records.length} records`);
}

Records are saved with field IDs rather than names, so renaming a field later doesn't break the export; schema.json maps each ID to its name and type. Attachment fields contain links that expire, so run the attachment script right afterwards if you need the files.

Each table takes one request per 100 records. Check your plan's monthly API allowance before exporting large bases on a Free workspace.

What no export includes

Interfaces, automations, extension settings, exact view configuration (filters, sorts, hidden fields, colors), permissions and record revision history stay in Airtable. Record comments are available through a separate API endpoint, one request per record. Write down your automations and take screenshots of important interfaces if you might need to rebuild them.

Keeping exports current

An export is a copy of one moment. If the base keeps changing, you'll need to repeat the export, keep older ones, and notice when one fails. That's the job a scheduled backup does; see how to back up Airtable for the options, and how to restore a base from a backup for getting an export back into Airtable.

Sources: Airtable's support article on views and CSV export, the Web API reference and rate limits, checked October 17, 2026.