Canva Bulk Create CSV Image Column: What Works and What Breaks
Draft — Post #52 · Target keyword: canva bulk create csv image · Meta: Your CSV has an image column but Canva Bulk Create leaves the slots blank. Here is exactly why the canva bulk create csv image wo

Draft — Post #52 · Target keyword: canva bulk create csv image · Meta: Your CSV has an image column but Canva Bulk Create leaves the slots blank. Here is exactly why the canva bulk create csv image workflow fails and how to fix it.
You exported a clean CSV. One row per design, every text field in its own column, and a column full of image URLs pointing at your product photos, headshots, or logos. You open Canva Bulk Create, upload the file, map the columns, hit generate, and the text comes through perfectly. The image slots are empty.
So you check the file again. The URLs are right there in the image column. They open fine in a browser. Nothing looks broken. But Canva treats that whole column like it does not exist, or worse, prints the raw URL as text inside your design.
This is the most common wall people hit with the canva bulk create csv image workflow. The fix is not a setting you missed. It is a format problem baked into how Canva reads spreadsheets. This post explains exactly what breaks, why, and the one step that makes the image column actually render.
Why Canva Bulk Create Ignores the Image Column in Your CSV
Canva Bulk Create reads two kinds of data: text and embedded images. Text is easy. Any value in a column gets merged into the matching placeholder. Names, prices, dates, SKUs, captions, all of it flows through without a fight.
Images are the catch. Canva only recognizes an image if it is physically embedded inside the spreadsheet file as binary data. In an XLSX, that embedded format is called DrawingML. A URL is not embedded image data. To Canva, https://yourstore.com/photos/mug.jpg is just a string of characters, the same as the word "mug." It either drops it or stamps the literal URL into your template.
A plain CSV makes this worse. CSV is a text-only format. It physically cannot hold an embedded image at all. So a CSV with an image URL column can never carry real image data into Canva, no matter how the column is named or mapped. We broke down the full technical reason in Why Canva Bulk Create Ignores Image URLs.
Canva's own help docs confirm it. Direct image URLs are not supported. Images have to be embedded directly in the cell or pulled from your Canva library, one image per cell, with no mixing of text and images in the same column. So the column that looks correct to you is invisible to Canva by design.
The Manual Workaround Most People Try First
Once people realize URLs fail, they reach for one of two manual hacks. Both technically work and both fall apart at scale.
The first is the Excel in-cell picture trick. Open the file in Excel, click an image cell, use Insert > Picture > Place in Cell, point to the downloaded file on your disk, and repeat for every row. Place in Cell is the key part, because a picture that floats over the grid will not export as embedded cell data the way Canva needs. This works if all your images are already downloaded, correctly sized, and named to match each row. For ten rows it is tedious. For two hundred it is most of an afternoon, and one misaligned row throws off everything below it.
The second is the =IMAGE() formula in Google Sheets. It looks like the perfect shortcut: drop the URL into =IMAGE("https://...") and the picture appears right in the cell. The problem is that =IMAGE() is a live formula, not embedded image data. When you download or convert the sheet, Canva sees an empty cell or a formula string, not a picture. We covered exactly why this dead-ends in Why =IMAGE() Doesn't Work for Canva Bulk Create.
So the honest summary is this. The manual methods can produce a working file, but only by spending the exact time Bulk Create was supposed to save you.
What You Need Before You Start
Two things have to be in place before the image column will work.
A Canva template with real placeholders. Your design needs Bulk Create text placeholders for each text field, like {{product_name}} or {{price}}, and at least one image element where the photo will land. Without an image element on the design, there is nowhere for the embedded picture to go.
A clean one-row-per-output spreadsheet. One row equals one finished design. One column per text field. One column holding the direct image URL, with nothing else mixed into it. Keep the image column pure: no captions, no notes, just the URL. Canva is strict about not mixing text and images in a single column, and a clean sheet is also what makes the conversion step reliable.
If your data already lives in Shopify, Etsy, Airtable, a database export, or a Google Sheet, you are most of the way there. The only column you may need to confirm is a direct, public image URL for each row. The same prep rules we use for Shopify product images apply here.
Step 1: Collect Direct Image URLs
The image column only works if each URL points straight at the image file, not at a preview or sharing page. A direct URL usually ends in .jpg, .png, or .webp.
For a store export, the product image URL is often already a direct link. For Google Drive, convert the share link to the https://drive.google.com/uc?id=FILEID&export=download form. For Dropbox, change the trailing ?dl=0 to ?raw=1. For anything on a website, right-click the image and choose Copy Image Address. If the link opens the picture by itself with no surrounding page, it will work.
Step 2: Build the Spreadsheet
Put one row per design and keep the image URL in its own dedicated column. A product sheet looks like this.
| product_name | price | tagline | image_url |
| Sunrise Mug | $24 | Start slow | https://store.com/img/mug.jpg |
| Trail Cap | $28 | Go far | https://store.com/img/cap.jpg |
| Field Tote | $32 | Carry less | https://store.com/img/tote.jpg |
Save it as CSV or XLSX. The column names do not have to match your Canva placeholders exactly, since you map them by hand in the Bulk Create panel, but matching names lets Canva auto-connect them in one click.
Step 3: Convert the CSV With Postprep
This is the step that turns the image column from text into something Canva can read.
Go to postprep.app, upload your CSV or XLSX, and pick the column that holds your image URLs. Postprep fetches each URL, downloads the actual image, and embeds it inside a new XLSX as DrawingML, the binary format Canva accepts. Every text column passes through untouched. What comes out is a spreadsheet where the image column is no longer a list of links but a column of real embedded pictures.
A 100-row sheet finishes in under a minute. The free tier covers 100 rows with no account required.
Step 4: Bulk Generate in Canva
Open your template in Canva on a plan that includes Bulk Create. Based on Canva's current documentation this covers paid tiers like Pro and Teams, and Bulk Create runs on desktop. Plan eligibility and feature names change, so confirm against your own account before a big run.
In the left panel open Apps, then Bulk Create. Click Upload data and choose the converted XLSX from Postprep. Drag each column onto its matching placeholder, including the now-embedded image column onto your image element. Click Generate designs. Canva builds one finished design per row with the photos already in place, then you download the set as a ZIP.
A Repeatable Workflow
Once the file is set up, the loop is fast every time. Export or update your spreadsheet so each row is one design and the image column holds direct URLs. Run it through Postprep to embed the images. Drop the converted XLSX into Bulk Create and generate. When your data changes, a new launch, a price update, a fresh batch of photos, you edit the same sheet, re-run the conversion, and regenerate. The image column behaves identically every time because the embedding step is doing the part Canva refuses to do.
If some rows are genuinely text-only, a quote card or a plain announcement with no photo, you do not need to convert those at all. Bulk Create handles text fine on its own. The conversion step is only for rows that carry an image.
Frequently Asked Questions
Does the image column work if I use a CSV instead of XLSX?
The CSV is fine as your starting file, but a CSV can never hold embedded images, so it cannot be the file you upload to Canva for the image step. Convert it to an XLSX with the images embedded first. Postprep does exactly that conversion.
My image column shows the URL as text inside the design. Why?
That means Canva is reading the column as text because the cells contain URL strings, not embedded images. Embed the images first, then map the column onto an image element rather than a text placeholder.
Can I have more than one image column?
Yes. If each output needs two pictures, for example a product photo and a logo, use two separate URL columns and convert both. Keep each image column pure, one URL per cell, no text mixed in.
Do the URLs have to be public?
The conversion needs to be able to fetch each image, so the URLs should be publicly reachable at convert time. Links behind a login or an expiring token may not download. Private store CDN links usually work; temporary signed links may not.
What if a row has no image yet?
Leave that cell blank. The image embed is skipped for empty cells and Canva keeps the placeholder visible in the generated design. Re-run the batch once the photo is ready.
Will the embedded images stay sharp at print size?
The image is embedded at whatever resolution the URL returns, so start from high-resolution sources if you plan to print. Low-resolution web thumbnails will look soft when scaled up.
The Short Version
The canva bulk create csv image column fails for one reason: Canva only reads images that are embedded inside the spreadsheet, and a CSV full of URLs is just text. The text columns merge fine. The image column stays blank because there is no real image data in it.
Build a clean sheet with one row per design and the image URLs in their own column. Convert it with Postprep so those URLs become embedded images. Then run Bulk Create in Canva and the image slots fill in on the first try.
Try it free at postprep.app — 100 rows, no account required.