Note
In this After Effects file you'll find a couple of different setups. They're all described below. I've also included a sample CSV.
CSV (or Comma-Separated Values) is an exchange format to store data in rows and columns. You can import and export them from Microsoft Excel or similar programs. However, I like to work directly on the .csv file in a code editing software (such as VS Code) or a text editor, because of a quirk in the file format: While confusingly being called Comma-Separated Values, CSV files can have different delimiters (most commonly semicolons and tabs), and Microsoft Excel will usually output semicolon-seperated values even if specified differently. On the other hand, After Effects will only accept actual comma-separated CSV files. To fix that, either export from Excel and replace all semicolons with commas in VS Code or use a simple online helper program to do the job for you. Or work directly in the CSV file and skip all that jazz.
This is the structure we're looking for:
Name, Profession, Age
Lucius Telljoy, Disgraced Magician, 43
Olialy Polly, Chilean singer-songwriter, 35
Playt Dill, , 40
The first line denotes the amount of columns, and each line below must have the same amount of commas. If a cell is supposed to be empty (like in the third line), just leave it empty. This will display like this:
| Name | Profession | Age |
|---|---|---|
| Lucius Telljoy | Disgraced Magician | 43 |
| Olialy Polly | Chilean singer-songwriter | 35 |
| Playt Dill | 40 |
Make sure to export CSVs in UTF-8 encoding to prevent special characters (ä,ü,ø,ß, ...) from breaking the text. This isn't always the default setting, and depending on your program of choice, you might have to specify while "Saving As".
The first line in a CSV is always the header, which After Effects can't read. If you want the header to be readable, insert a blank first line.
The way we access the CSV file is using a direct footage("CSV.csv") call — well, kind of, I'll get to it — which means it doesn't reference the layer in the current composition. However, it's generally a good idea to always drop a CSV file into all comps you're using it in. If you don't, Collect Files or Reduce Project using After Effect's Dependencies tools will get rid of the file, because those tools don't look for Expression references to files. And, since Collect Files is what After Effects does when you send a project to Media Encoder, your CSV data will simply not show up there.
That's why I like to reference the CSV like this:
const CSVFile = thisComp.layer(1).source;
Instead of the classic way:
const CSVFile = footage("CSV.csv");
This means that the CSV has to be the first layer in the comp. This effectively makes the CSV behave like a normal footage item — in the way that expressions will break if it's no longer in the comp (which is a good thing). Bonus: You can replace the CSV with a differently named one without having to go into expressions to update the CSV file name. It's just less likely to cause problems that are a headache to clean up. Be careful doing it like this with huge CSV files though, because...
Yep: Every time a CSV is dragged into a composition, its whole structure is replicated as Pseudo Effects on that layer, and that blows up the size of the After Effects file. With a huge CSV referenced in a lot of comps you can easily climb to a couple of GBs for an After Effects Project. If that's the case, my expression setup isn't really the best way to do it anymore.
The bigger the CSV file and the more often it's referenced, the more performance issues you're likely to run into. To mitigate that problem, use posterizeTime(0); in the beginning of Expressions referencing the file to make After Effects calculate it just once on the first frame. This will make the entire property static and will ignore keyframes, so only use when you don't want to animate that property. I like to have the Render Time visible in the timeline to see what's eating performance.
Tip
Layers with Opacity: 0 are not rendered and thus don't impact render time. That's why I like to have the more complicated expressions on Null Objects (usually called CTRL), because Nulls by default have their opacity set to 0. You can also use conditional statements to figure out when a layer is no longer visible on screen and then turn the Opacity to 0.
This is the basic rig I like to use. The sourceText grabs the value from the CSV file using two Slider Controls to act as line and column selectors. I like to link those up to the layer name, because you're likely to have lots of layers referencing different bits of the CSV and this is a great way to duplicate layers to create news lines of text. You can, of course, disable the Expression on the Slider Controls to control them manually.
These are some of those CSV Text layer Rigs in action, paired with dynamic placing in rows and columns. The layer name controls the placing of the Text layers, and there's basic styling Pseudo Effects available to control cell sizes and paddings.
Here the line and column Pseudo Effects were linked up the the comp name—while having static columns (e.g. Title/Subtitle), duplicating the comp (thus incrementing the suffix by one) will select the next line, updating the text accordingly. Great to set up line 1 just how you like it and then duplicate as many times as you need.


