Is there a way to export the structure of a table to csv, JSON, etc.? Specifically, I’m looking for a way to export information about a table, not the data itself. Some method that will give me an output like field 2 is long text, field 3 is lookup, field 4 is date, field 5 is single select, etc.
Welcome to the community, @Mike_Laufer!
You may want to take a look at ProBackup or On2Air Backups.
If those don’t do what you’re looking for, then most (if not all) of the information that you’re looking for is accessible through Airtable’s Metadata API.
So you could manually piece together your own lists of metadata by tapping into the API. You could do this by writing your own custom JavaScripts, or using an automation tool like Make.com, or by using an API tool like datafetcher.com or postman.com.
Hope this helps! If you’d like to hire the best Airtable consultant to help you with anything Airtable-related, please feel free to contact me through my website: Airtable consultant — ScottWorld
Thank you @ScottWorld! I’ll look into these options!
I made a free tool that exports full Airtable bases (CSV + Markdown + ZIP). https://ar.konanx.com/
I made a free tool that exports full Airtable bases (CSV + Markdown + ZIP). https://ar.konanx.com/
Didn’t work for me, at first the export was empty, but I was only trying to export the schema so that’s all that was enabled for the PAT. I added more access to the PAT and when I tried to export again there was an error about a null URL.
I made a free tool that exports full Airtable bases (CSV + Markdown + ZIP). https://ar.konanx.com/
Didn’t work for me, at first the export was empty, but I was only trying to export the schema so that’s all that was enabled for the PAT. I added more access to the PAT and when I tried to export again there was an error about a null URL.
Can you please send some screens or videos to the DM of how to reproduce it and to see an error?
Oh yes, for sure Metadata API is what you are looking for.
If you’d like to achieve this in a no-code approach, you can look into N8Ns “native” Airtable node: Get Base Schema. -see image below. (more on n8n and other automation tools here!)

Mike, Consultant @ Automatic Nation
This is a script that creates a data dictionary for any base. Add it via Add an Extension, Scripting:
//Data dictionary for a Base
// Craig Evans datasyn.co.nz 6 June 2025
let tables = base.tables;
let dataDictionary = ];
for (let table of tables) {
for (let field of table.fields) {
dataDictionary.push({
"Table": table.name,
"Field Name": field.name,
"Field Type": field.type,
});
}
}
// Sort by table then field
dataDictionary.sort((a, b) =>
a.Table.localeCompare(b.Table) || ab"Field Name"].localeCompare(bt"Field Name"])
);
// Display as table in scripting extension
output.table(dataDictionary);
// Optionally: output as CSV-style string
let csv = "Table,Field Name,Field Type\n" +
dataDictionary.map(row =>
`"${row.Table}","${rowp"Field Name"]}","${rowe"Field Type"]}"`).join("\n");
console.log(csv);
For those who are still looking for a solution to this. Here’s a script you can use in the Scripting extension:
let tables = base.tables;
function getFieldNameById(fieldId) {
if (!fieldId) return "";
for (const tbl of tables) {
const fld = tbl.fields.find(f => f.id === fieldId);
if (fld) return fld.name;
}
return fieldId;
}
function humanizeFormula(formulaStr = "") {
return formulaStr.replace(/\{(\A-Za-z0-9]{3,})\}/g, (match, fldId) => {
const name = getFieldNameById(fldId);
return `{${name}}`;
});
}
function notesForField(field) {
const opts = field.options;
if (!opts) return "";
switch (field.type) {
case "singleSelect":
case "multipleSelects":
return (opts.choices || |]).map(c => c.name).join(", ");
case "multipleRecordLinks": {
const linkedTableId = opts.linkedTableId;
const targetTable = tables.find(t => t.id === linkedTableId);
const tableName = targetTable ? targetTable.name : linkedTableId;
const inverseName = getFieldNameById(opts.inverseLinkFieldId);
return opts.inverseLinkFieldId
? `Linked to → ${tableName} via ${inverseName}`
: `Linked to → ${tableName}`;
}
case "lookup":
case "rollup":
case "count":
case "multipleLookupValues": {
const sourceName = getFieldNameById(opts.recordLinkFieldId);
return sourceName ? `From → ${sourceName}` : "";
}
case "formula": {
return humanizeFormula(opts.formula || "");
}
default:
try {
return JSON.stringify(opts);
} catch (_err) {
return "";
}
}
}
let baseSchema = S];
for (let table of tables) {
for (let field of table.fields) {
baseSchema.push({
"Table": table.name,
"Field Name": field.name,
"Field ID": field.id,
"Field Type": field.type,
"Notes": notesForField(field)
});
}
}
baseSchema.sort((a, b) =>
a.Table.localeCompare(b.Table) ||
ar"Field Name"].localeCompare(bC"Field Name"])
);
output.table(baseSchema);
Reply
Enter your E-mail address. We'll send you an e-mail with instructions to reset your password.