cfimp is a simple but powerful CLI tool for importing/updating CSV data in the Contentful headless CMS. The default delimiter is tab.
In the process, entries can optionally be linked to (existing) assets, tags or references (foreign items), and published.
cfimp cannot be used to create new assets, tags, models or anything other than entries.
cfimp is best used via
npx and doesn't need to be installed onto your machine.
2) Authenticate with Contentful (optional).
Authenticating this way will save the credentials in your environment so you don't have to authenticate manually each time you use cfimp. If you'd rather do that instead, though, see the
Example 1: Import tab-separated data from input.csv to space "12345" / content type (model) "authors" / locale "en-GB"
Example 2: Also specify some tags (for all rows), and this time let's assume comma-separated data
Example 3:Specify a fallback (default) value "bar" for the "foo" field
Example 4: Preview the generated JSON of the first entry - no actual import takes place
Note: the default delimiter is tab! You can change this via
It's strongly recommended to preview the generated data before running the write. See the
cfimp should be used via
Arguments are specified in the format
* or, where the argument doesn't accept a value (denoted
-arg below), simply
-arg:"one two" contains spaces, use
Valid arguments are as follows:
input- path to the input file (optional; default: "input.csv")
model- the ID of the Contentful model (content type) to write to (required)
space- the ID of the Contentful space to write to (required)
dfltvals- a com-sep list of
field=valuedefaults to use anywhere a row has empty cells. See Merge and default values (optional)
mergevals- a com-sep list of
field=valuepairs to merge into all rows. See Merged and default values (optional)
delim- the delimiter separating columns (for multi-column files) - one of "tab", "com" (comma) or any other string (optional; default: "tab")
fields- the fields to import into. If omitted, cfimp will assume the first row of the input data denotes the fields (optional)
locale- the locale, as defined in Contentful, e.g. "[en-GB]". See Writing to multiple locales (required)
enc- the file encoding for your data (you shouldn't need to change this) - one of "utf8", "ascii" or "base64" (optional; default: "utf8")
preview*- if passed, shows a preview of the data that will be written to Contentful; no write is performed. See Troubleshooting (optional)
env- the ID of the Contentful environment to write to (optional; default: "master")
skipfields- a com-sep list of field IDs to ignore from the input. Useful if your spreadsheet export contains columns you don't want to include (optional)
publish*- sets the imported/updated entries to "published" status rather than "draft" (optional)
offset- a 1-index offset (row) to begin reading data from in your input file (optional)
limit- a limit as to the number of rows to process (optional)
skiprows- a com-sep list of strings which, if any is found in a row (any column), will cause that row to be skipped OR included. See Filtering rows (optional)
nocast- ordinarily, numbers, true and false will be cast to their integer/boolean equivalents when data is passed to Contentful. Pass true to prevent this (i.e. if you literally want to pass "true" not
tagall- a com-sep list of (existing) tags to tag all entries with. You can also specify row-specific tags. See Tagging items (optional)
listdelim- the delimiter to look for in all arguments that accept a list e.g.
fieldsetc (optional; default: ",")
mtoken- a management token to authenticate with Contentful. You can omit this if you've already authenticated via
Reference and asset links 🔗
It's possible to link to existing assets or references (i.e. foreign items in other content types) via the
ref- (reference) and
refa- (asset) prefixes.
In both cases, you'll need to know the ID of the item you're linking to.
Let's say you have a field on your content type called "authorBioPhoto" and, in preparing your data, you've ascertained the various asset IDs you want to link each author to. Your data would look something like:
If for some reason all our authors have the same face and photo, we can even specify this at runtime with a merge value (see
Merged and default values 🔗
It's possible to specify default fallback values for your data, which will take effect if the cell is empty for that field.
It's also possible to merge extra data with all rows.
Let's say you have a field in your data, "popular", with some rows having "yes" as a value. For all others, with no value, you want to insert "no".
Or let's say you want to add an extra field to all rows. Perhaps you meant (but forgot) to add an "age" column to your spreadsheet data before exporting it, and it so happens that, surprisingly, all the authors in your data are 51. We can add this via:
Updating existing items 🔗
cfimp can be used to update existing items in Contentful rather than import (create) new ones. To do this, include an
_id column in your data. This will be inferred as the internal Contentful ID of the item, and will update it.
Multiple locales 🔗
All data in Contentful is stored against locales, created by you in Contentful. This allows you to have multiple versions of each piece of data, for different locales. By default, cfimp will import/update data using the locale specified in the
However you can import/update multiple locales at once. To do so, specify the field as many times as you have locales, with each additional one appended with a locale flag.
So if your data was:
You can spefify locales either in the data itself, if the first row of data represents your field IDs:
...or via the
fields argument, if you're specifying field IDs at runtime.
The first city will use the "en-GB" locale passed in via the locale arg; the second one will use the explicitly-set "es-SP" locale.
Tagging items 🔗
It's possible to tag items to (existing) tags when importing or updating items. There are two ways to do this.
You can specify item-specific tags in your data, via the
You can also tag all items at runtime via the
Filtering rows 🔗
It's possible to stipulate which rows you do, or do not, want to be imported/updated from your input file, via the
This argument is used to whitelist or blacklist certain rows, and accepts a com-sep list of values to blacklist or, if the entire argument value is prefixed with
!, to allow.
The following will blacklist (skip) any rows that contain, in any column, "foo" OR "bar":
The following will whitelist (include) any rows that contain "foo" OR "bar"; all other rows will be skipped:
Publishing items 🔗
cfimp can publish entries when importing or updating them. To stipulate this, pass the
publish argument. If this is omitted, the entry will end up in draft status or, for updated entries, whatever its current status is.
Note that, when importing and publishing new items, cfimp will generate item IDs itself, rather than leave it to Contentful. This is a requirement of Contentful's import tool; in order to publish the items, it requires a contrived ID to be generated by the client.
This has no bearing on anything; such entries will have a valid Contentful ID, in the format
cfimp.*. (The prefix ensures such generated IDs can never clash with Contentful-generated IDs.)
Delimiter Overrides 🔗
Delimiters are factors in two areas of cfimp:
- the delimiter used to separate the values in your input file
- the delimiter used to separate any (normally) comma-separated pairings in arguments or
Both of these can be overriden - the former via the
delim arg and the latter via the
listdelim arg. Note that
listdelim will apply to all occasions where cfimp is attempting to decipher something that it normally expects to be in com-sep format - so for example
_tags fields, the
mergevals argument, and so on.
It's HIGHLY recommended to preview the generated data before running the actual import/data. This shows you what cfimp intends to send to Contentful for import/update.
You can do this via the
preview argument, i.e.
A limit is handy in order to avoid numerous terminal screens of data.
If you find cfimp is deriving or malformed bad data, check the
Did I help you? Feel free to be amazing and buy me a coffee on Ko-fi!