Export · CSV
Export your X bookmarks to Airtable
Airtable is the destination that handles repeat exports best: its CSV import can merge on a field, so setting the merge key to the post ID makes every subsequent download an update rather than another five hundred rows.
Two ways in, and they are not equivalent
| Route | What it does | Use it when |
|---|---|---|
| New base from CSV | Creates a base and a table, inferring a field type per column. Fast, and gets two of them wrong. | The first import, before there is anything to preserve. |
| CSV import extension into an existing table | Maps CSV columns onto fields you already configured, and optionally merges on a field you nominate instead of appending. | Every import after the first. This is the one that makes the daily cap painless. |
The order matters. Import once to get a table, fix the field types, and from then on use the extension with post_id as the merge field. Do it the other way around and you spend an evening deduplicating.
Setting it up
Comma-separate the tags column first
Ourai_tagscolumn is space-separated. Airtable creates Multiple select options by splitting on commas, so left alone you get one option readingcaching infra performance. Substituting commas for spaces in that one column — in a spreadsheet, or via the in-browser converter — is thirty seconds of work that saves rebuilding the field later.Import the CSV to create the table
Add a base, choose to import a CSV, pick the file. Airtable produces a table with nine fields and a guess at each type. Do not build views yet.Fix post_id before anything else
If Airtable typed it as Number, change it to Single line text and then re-import. Converting the field back to text keeps whatever the number field was holding, and a 19-digit integer is not something a numeric field held faithfully in the first place. This is the one step where repairing in place does not work.Set the remaining types
Per the table below. Six of the nine want something other than the default.Turn the primary field into something readable
Airtable’s primary field is whatever landed in the first column and cannot be deleted, though unlike some tools it can be renamed and retyped. Point it atai_summary, or add a formula field concatenating the handle and the first few words of the post, so linked records elsewhere in the base show something meaningful.Import again tomorrow with a merge key
Open the CSV import extension, map the columns, and set the merge field topost_id. Airtable updates matching records and inserts the rest. Overlapping exports stop mattering, which is the difference between this and the Notion route, where a second CSV simply appends.
Field mapping
| CSV column | Airtable field type | Why this one |
|---|---|---|
post_id | Single line text | The merge key. Must be text: see step 3. |
post_url | URL | Clickable from grid and from the expanded record. |
author_handle | Single line text | Or Single select, if you want a grouped-by-author view and can tolerate a long option list. |
posted_at | Date with time | Set the field to display in your timezone; the underlying value stays UTC. |
saved_at | Date with time | The sort field for a chronological view. |
post_text | Long text, rich text OFF | Long text preserves the newlines in a post. Rich text would reinterpret characters in it — see below. |
ai_category | Single select | Airtable offers to create one option per distinct value on conversion. Fixed vocabulary, so the list stays short. |
ai_tags | Multiple select | Only after the comma substitution in step 1. |
ai_summary | Long text or Single line text | Good candidate for the primary field. |
What the base is actually for
The reason to put saved posts in Airtable rather than a plain spreadsheet is that the field types are enforced rather than merely suggested, and the views are cheap. Group a grid by ai_category and you have the sorted library, in a tool where you can add your own fields next to it: a status field for read or unread, a checkbox for “actually useful”, a link to whatever project the post is relevant to. That last one is the thing a CSV cannot do and a bookmark manager should not try to.
Two limits to know before you commit to it. Airtable’s lower plans cap records per base, and 500 rows per export day reaches a low cap faster than people expect — check yours against the size of your bookmark library rather than against a single import. And long text fields count toward per-record size limits, so a base of several thousand posts with your own attachments alongside is heavier than the row count suggests.
Automations, and a boundary worth respecting
Airtable automations can fire on a new record and send it almost anywhere, and it would be straightforward to wire this table into Slack, an email, or a public interface. Two things to keep in view if you do.
The first is that we do not push into Airtable, and will not. X’s developer policy restricts handing X content to third parties and makes an exception for up to 500 post objects per person per day by non-automated means — a file you download. A scheduled write into your base would be an automated delivery of post content to a third-party service, which is not covered by that exception, so the download button is the deliberate stopping point.
The second is that the same rules follow the data. Once post text is in your base, an automation that republishes it to a public interface or a shared channel is a redistribution decision you are making, not one we made for you. Keeping the base private and the ai_ prefix intact on the generated fields is the low-effort way to stay on the right side of it. Posts deleted on X, incidentally, never enter the base at all — a the deletion check that runs every night takes them out of the export first.
Two things that are true of every export
Sort them first, then export
An export is only worth having if the categories are. Connect X read-only, let Sift import and sort your newest bookmarks, and the file you download inherits that structure — category, tags and a one-line summary already attached to every row.
Connect X