---
title: "Batch Image Generation from CSV (Guide)"
description: "Generate thousands of images from a CSV or spreadsheet. Upload your data, map columns to template fields, and download results. Code and no-code methods."
url: "https://www.imejis.io/blogs/tutorials/batch-image-generation-csv"
published: "2026-03-24"
---

# Batch Image Generation from CSV (Guide)

Batch image generation from a CSV is the fastest way to turn a spreadsheet into thousands of branded images. You have 500 products, each needing an image with name, price, photo, and sale badge. Doing this by hand in Canva would take days.

I ran this exact workflow last month for an e-commerce client. 500 product images, generated in about 15 minutes from a CSV export. Here's the complete process with both code and no-code methods. All pricing is as of March 2026.

## How Batch CSV Image Generation Works

The process is three steps:

1. **Design a template** with dynamic fields (text, images, colors)
2. **Prepare your CSV** with one row per image, columns matching your template fields
3. **Loop through the CSV** and call the API for each row

That's it. Each row becomes one image.

## Step 1: Design Your Template

Create a template in [Imejis.io](https://www.imejis.io) with layers that match your data. For a product catalog, that might be:

- `product_name`: text layer
- `price`: text layer
- `product_image`: image layer
- `discount_badge`: text layer (optional, for sale items)
- `background`: shape with fill color

Name your layers clearly. These names become the column headers in your CSV. Name your layers clearly so they map directly to your CSV column headers.

## Step 2: Prepare Your CSV

Structure your spreadsheet so each column maps to a template layer:

```csv
product_name,price,product_image,discount_badge
Classic Runner,$29.99,https://cdn.example.com/runner.jpg,40% OFF
Urban Jacket,$89.00,https://cdn.example.com/jacket.jpg,
Wool Beanie,$15.99,https://cdn.example.com/beanie.jpg,NEW
Canvas Tote,$24.50,https://cdn.example.com/tote.jpg,25% OFF
Leather Belt,$45.00,https://cdn.example.com/belt.jpg,
```

A few things to get right:

- **Image URLs must be publicly accessible.** The API fetches the image from the URL you provide. If it's behind authentication or on localhost, it won't work.
- **Empty cells are fine.** If a product has no discount, leave the `discount_badge` column empty. The template layer stays as designed (or hidden, if you set it up that way).
- **Watch your encoding.** Save as UTF-8 if you have special characters, accents, or non-Latin text.

## Step 3: Generate Images

### Method A: Node.js Script

```javascript
import fs from "fs"
import { parse } from "csv-parse/sync"

const API_KEY = process.env.IMEJIS_API_KEY
const TEMPLATE_ID = "YOUR_TEMPLATE_ID"

// Read and parse CSV
const csvData = fs.readFileSync("products.csv", "utf-8")
const rows = parse(csvData, { columns: true, skip_empty_lines: true })

console.log(`Processing ${rows.length} products...`)

for (const [index, row] of rows.entries()) {
  const payload = {
    product_name: { text: row.product_name },
    price: { text: row.price },
    product_image: { image: row.product_image },
  }

  // Only include discount badge if it has a value
  if (row.discount_badge) {
    payload.discount_badge = { text: row.discount_badge }
  }

  const response = await fetch(`https://render.imejis.io/v1/${TEMPLATE_ID}`, {
    method: "POST",
    headers: {
      "dma-api-key": API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(payload),
  })

  const buffer = Buffer.from(await response.arrayBuffer())
  fs.writeFileSync(`output/product_${index + 1}.png`, buffer)

  console.log(`Generated ${index + 1}/${rows.length}: ${row.product_name}`)
}

console.log("Done!")
```

### Method B: Python Script

```python
import csv
import requests
import os

API_KEY = os.environ['IMEJIS_API_KEY']
TEMPLATE_ID = 'YOUR_TEMPLATE_ID'

with open('products.csv', 'r') as f:
    reader = csv.DictReader(f)
    rows = list(reader)

print(f'Processing {len(rows)} products...')

for i, row in enumerate(rows):
    payload = {
        'product_name': {'text': row['product_name']},
        'price': {'text': row['price']},
        'product_image': {'image': row['product_image']}
    }

    if row.get('discount_badge'):
        payload['discount_badge'] = {'text': row['discount_badge']}

    response = requests.post(
        f'https://render.imejis.io/v1/{TEMPLATE_ID}',
        headers={
            'dma-api-key': API_KEY,
            'Content-Type': 'application/json'
        },
        json=payload
    )

    with open(f'output/product_{i + 1}.png', 'wb') as img:
        img.write(response.content)

    print(f'Generated {i + 1}/{len(rows)}: {row["product_name"]}')

print('Done!')
```

### Method C: No-Code (Google Sheets + Zapier)

If you don't want to write code:

1. **Upload your CSV to Google Sheets**
2. **Create a Zap** with trigger "New Spreadsheet Row in Google Sheets"
3. **Add an action**: Webhooks by Zapier > POST request
4. **Configure the request**:
   - URL: `https://render.imejis.io/v1/YOUR_TEMPLATE_ID`
   - Headers: `dma-api-key: YOUR_API_KEY`
   - Body: Map spreadsheet columns to JSON fields
5. **Turn on the Zap**: each new row generates an image

The same approach works with Make.com or [n8n](https://n8n.io). In n8n, use a Spreadsheet File node to read the CSV, then loop through rows with an HTTP Request node. For a complete walkthrough of the Google Sheets approach, see our guide on [generating images from Google Sheets and uploading to Drive](/blogs/integrations/zapier/generate-images-google-sheets-with-imejis-and-upload-to-drive).

### Method D: Airtable + Make

If your data lives in Airtable:

1. **Create a Make scenario** triggered by "Watch Records" in Airtable
2. **Add an HTTP module** that calls the Imejis.io API
3. **Map Airtable fields** to the JSON payload
4. **Optionally upload** the generated image back to an Airtable attachment field

This creates a live pipeline: add a row to Airtable, get an image generated automatically.

## Handling Large Batches

### Speed Expectations

| Batch Size   | Sequential (1 at a time) | Parallel (5 at a time) |
| ------------ | ------------------------ | ---------------------- |
| 100 images   | ~3 minutes               | ~40 seconds            |
| 500 images   | ~17 minutes              | ~3.5 minutes           |
| 1,000 images | ~33 minutes              | ~7 minutes             |
| 5,000 images | ~2.8 hours               | ~35 minutes            |

### Adding Parallelism (Node.js)

For large batches, run multiple requests at once:

```javascript
const BATCH_SIZE = 5 // Process 5 images simultaneously

for (let i = 0; i < rows.length; i += BATCH_SIZE) {
  const batch = rows.slice(i, i + BATCH_SIZE)

  await Promise.all(
    batch.map(async (row, j) => {
      const response = await fetch(/* ... */)
      const buffer = Buffer.from(await response.arrayBuffer())
      fs.writeFileSync(`output/product_${i + j + 1}.png`, buffer)
    })
  )

  console.log(
    `Batch complete: ${Math.min(i + BATCH_SIZE, rows.length)}/${rows.length}`
  )
}
```

Start with a batch size of 5. Increase if your plan's rate limits allow it.

### Error Handling

Real CSV data has issues. Some rows will have missing URLs, empty fields, or encoding problems. Add basic error handling:

```javascript
try {
  const response = await fetch(/* ... */);
  if (!response.ok) {
    console.error(`Failed row ${index}: ${response.status}`);
    continue;
  }
  // save image...
} catch (err) {
  console.error(`Error on row ${index}: ${err.message}`);
  continue;
}
```

Log failures but don't let one bad row stop the entire batch.

## Common CSV Pitfalls

**Commas in data.** If your product names contain commas ("Running Shoe, Men's"), wrap them in quotes in the CSV or use a tab-separated format instead.

**Image URLs with spaces.** URL-encode spaces as `%20`. Some CSV exports from e-commerce platforms include unencoded spaces in URLs.

**Excel encoding.** Excel sometimes saves CSV with BOM (byte order mark) or Windows line endings. If you're getting parse errors, re-save as UTF-8 without BOM.

**Missing headers.** The first row of your CSV must be column headers. If it's not, the script won't know which column maps to which template field. I've debugged this one more times than I'd like to admit.

## Cost Breakdown

| Volume  | Imejis.io Plan | Monthly Cost | Per Image |
| ------- | -------------- | ------------ | --------- |
| 100     | Free           | $0           | $0.00     |
| 1,000   | Basic          | $14.99       | $0.015    |
| 10,000  | Pro            | $24.99       | $0.0025   |
| 100,000 | Unlimited      | $69.99       | $0.0007   |

At the Pro level, generating 5,000 product images from a CSV costs about $12.50 worth of API calls. Compare that to a designer spending 3-5 minutes per image in Canva. At 5,000 images, that's 250-400 hours of design time.

## Getting Started

1. **[Sign up for Imejis.io](https://app.imejis.io)**: 100 free images per month
2. **Design a template** with clearly named layers
3. **Prepare a test CSV** with 5-10 rows
4. **Run the script** (or set up the Zapier workflow)
5. **Check the output** for any layout issues
6. **Process your full dataset** once the template is validated

For the JSON data format details, see our [Generate Images from JSON](/blogs/tutorials/generate-images-from-json) guide. For pricing across all providers, check our [Image Generation API Pricing Comparison](/blogs/comparisons/image-generation-api-pricing-comparison). And for e-commerce specifically, see [Dynamic Product Images with Live Pricing](/blogs/use-cases/dynamic-product-images-pricing).

## FAQ

### Can I generate images from a CSV file?

Yes. Read each row, call an image API like [Imejis.io](https://www.imejis.io) with the row data, and save the result. Each row becomes one image with the correct data from your spreadsheet.

### How long does it take to generate 1,000 images from a CSV?

About 33 minutes sequentially, or 7 minutes with 5 parallel requests. Each image generates in under 2 seconds. [Imejis.io Pro](https://www.imejis.io/pricing) ($24.99/month) covers 10,000 images.

### Can I do this without coding?

Yes. Upload your CSV to Google Sheets or [Airtable](https://airtable.com), then use [Zapier](https://zapier.com) or [Make](https://www.make.com) to loop through rows and call the API. Setup takes about an hour. You can also [share designs with public links](/blogs/share-design-with-public-links) for a completely code-free option.

### What CSV columns do I need?

Columns matching your template's dynamic fields. If the template has `headline`, `price`, and `product_image` layers, your CSV needs columns with those names and data for each row.

### How much does bulk image generation cost?

Imejis.io's [free tier](https://www.imejis.io/pricing) covers 100/month. Pro ($24.99) covers 10,000 at $0.0025 per image. That's a fraction of the cost of manual design.

## Stop Designing One Image at a Time

Your data is in a spreadsheet. Your template is ready. The script is 20 lines of code. [Try Imejis.io free](https://app.imejis.io) and batch-generate your first 100 images today.
