Shopify CSV Import: Products, Customers & Orders Guide
How to import CSV files into Shopify - products with variants, customer data, and multi-location inventory. Error solutions, image requirements, and when third-party apps actually help.

Shopify lets you bulk upload products, customers, and inventory through CSV files. If you're migrating from another platform or just need to update a few thousand product prices, CSV imports beat clicking through the admin one product at a time.
I'll walk through the three import types, what columns you actually need, how variants work (this trips people up), and the errors you'll probably hit. Also when Shopify's built-in importer falls short and you need something else.
Three Types of Shopify CSV Imports
Shopify has three separate import types. They don't share columns, so you can't just mash all your data into one file.
1. Product CSV Import
This is the one most people need. It handles your catalog—titles, descriptions, prices, variants, images.
| Feature | Details |
|---|---|
| File Size Limit | 15 MB per file |
| File Format | UTF-8 encoded CSV |
| Plan Availability | All Shopify plans |
| Cancellation | Cannot be cancelled once started |
2. Customer CSV Import
For importing customer records—contact info, addresses, and metafields.
| Feature | Details |
|---|---|
| File Size Limit | 15 MB per file |
| Required Column | Email (column must exist, value can be blank) |
| Headers | Case-insensitive |
| Password Migration | Not supported |
The password thing is annoying—customers from your old platform have to reset their passwords. No way around it. Plan to communicate this during migration.
3. Inventory CSV Import
Updates stock quantities across locations. Separate from product imports (which can confuse people at first).
| Feature | Details |
|---|---|
| File Size Limit | 15 MB per file |
| Export Formats | "All states" (recommended) or "Available" only |
| Multi-Location | Yes, separate rows per location |
| Safety Validation | Compares "On hand (current)" vs actual |
Required inventory CSV columns include Handle, Location, and either SKU or Option1 Name + Option1 Value.
How to Import Products via CSV
Here's the actual process:
- From Shopify admin, go to Products
- Click Import
- Click Add file and pick your CSV
- Deselect "Publish new products to all sales channels" if you want to review first (I usually do)
- Check "Overwrite products with matching handles" if you're updating existing products
- Click Upload and continue
- Review what Shopify shows you
- Click Import products
You'll get an email when it finishes. One thing that catches people off guard: you can't cancel once you click import. So double-check your CSV before you commit.
According to Shopify's documentation: "Your product CSV can't exceed 15 MB. If you get an error after trying to upload a new CSV file, or if the upload times out, split the CSV file into multiple smaller files, and then upload each file."
Complete Product CSV Column Reference
There are a lot of columns. You won't need most of them, but here's what each one does so you don't have to guess.
Required Columns
| Column | Requirement | Notes |
|---|---|---|
| Title | Required for new products | Product display name |
| URL handle | Required for variants and updates | Unique identifier in URLs |
| Option1 Name/Value | Required for variants | Use "Title"/"Default Title" for products without options |
All Product CSV Columns
| Column | Description | Default Value |
|---|---|---|
| Title | Product name | Required |
| URL handle | Unique URL identifier | Auto-generated from title |
| Description | HTML product description | Empty |
| Vendor | Product origin/source | Store name |
| Product category | Shopify Standard Product Taxonomy | None |
| Type | Custom product type label | Empty |
| Tags | Comma-separated keywords | Empty |
| Published on online store | true or false | true |
| Status | active, draft, archived | active |
| SKU | Stock keeping unit | Empty |
| Barcode | UPC/ISBN/barcode | Empty |
| Option1 Name | Variant option name (e.g., "Size") | "Title" |
| Option1 Value | Variant option value (e.g., "Small") | "Default Title" |
| Option2 Name | Second option (e.g., "Color") | Empty |
| Option2 Value | Second option value | Empty |
| Option3 Name | Third option (e.g., "Material") | Empty |
| Option3 Value | Third option value | Empty |
| Price | Variant price (numeric only) | 0.00 |
| Compare-at price | Original price for sale display | Empty |
| Cost per item | Your cost for profit tracking | Empty |
| Charge tax | true or false | true |
| Inventory tracker | shopify, shipwire, amazon_marketplace_web, or blank | Empty |
| Inventory quantity | Stock count (single location only) | 0 |
| Continue selling when out of stock | deny or continue | deny |
| Weight value (grams) | Weight in grams (integers only) | 0 |
| Weight unit for display | g, kg, lb, oz | kg |
| Requires shipping | true or false | true |
| Fulfillment service | manual or custom service name | manual |
| Product image URL | Publicly accessible image URL | Empty |
| Image position | Display order (1 = first) | Auto |
| Image alt text | SEO/accessibility text (max 512 chars) | Empty |
| Variant image URL | Variant-specific image URL | Empty |
| SEO title | Search engine title (max 70 chars) | Uses Title |
| SEO description | Search engine description (max 320 chars) | Uses Description |
Important: Price values should be numeric only without currency symbols. Enter 19.99 not $19.99.
Variant Product Handling
Variants are different versions of a product—size, color, material, that kind of thing. Shopify allows up to 3 option types per product. So you could have Size × Color × Material, but not Size × Color × Material × Length.
How Variants Work in CSV
This is where people get confused. The CSV structure is a bit weird:
- First row: Has all the product-level stuff (title, description, tags) PLUS the first variant's data
- Following rows: Same URL handle, but leave product fields blank—just the variant-specific columns
Variant CSV Example
Here's a t-shirt with Size and Color variants. Look at how rows 2-4 repeat the handle but skip title/description:
Handle,Title,Description,Option1 Name,Option1 Value,Option2 Name,Option2 Value,Price,SKU
t-shirt,Basic T-Shirt,Comfortable cotton,Size,Small,Color,Red,19.99,TSH-SM-RED
t-shirt,,,Size,Small,Color,Blue,19.99,TSH-SM-BLU
t-shirt,,,Size,Medium,Color,Red,19.99,TSH-MD-RED
t-shirt,,,Size,Medium,Color,Blue,19.99,TSH-MD-BLU
Each row = one variant combination. The repeated handle tells Shopify these all belong to the same product.
Products Without Variants
Even "simple" products need variant columns. Use:
- Option1 Name:
Title - Option1 Value:
Default Title
Shopify requires this internally. It's a quirk, but you get used to it.
Watch Out: Variant IDs Can Break
This bit me once. From Shopify's docs: "Changing data in this column [Option1 value] deletes existing variant IDs' values and creates new variant IDs. Any change to variant ID values can break third-party dependencies on variant IDs."
Translation: if you change option values on existing products, you might break things like:
- Third-party apps that track inventory by variant ID
- External systems pointing to specific variants
- Subscriptions tied to those variant IDs
If you're updating existing products, either match option values exactly or use an app like Matrixify that preserves variant ID associations.
Variant Limits
- Max 3 option types per product (like Size, Color, Material)
- If your store has 50,000+ variants, you're capped at 1,000 new variants per day (unless you're on Shopify Plus)
Hit that limit? You'll see "Daily variant creation limit reached." Split your import across days or upgrade your plan.
Image URL Requirements
Images are where a lot of imports fail. Here's what Shopify needs:
| Requirement | Details |
|---|---|
| Protocol | Must use https:// |
| Accessibility | Must be publicly accessible |
| File Types | PNG, JPG, GIF (standard web formats) |
| Size Limit | Maximum 25 megapixels (5000 x 5000 px) |
| Per Product | Up to 250 images |
| Naming | Avoid _thumb, _small, _medium suffixes |
| 3D/Video | Not supported in CSV |
The key is "publicly accessible." If you need to log in to view the image, Shopify can't fetch it. Uploading to Content > Files in Shopify admin first is the safest approach.
Adding Multiple Images Per Product
To add multiple images to a single product, create additional rows with the same Handle value and only populate the image-related columns:
Handle,Title,Product image URL,Image position,Image alt text
blue-sneaker,Classic Blue Sneaker,https://cdn.example.com/sneaker-front.jpg,1,Front view
blue-sneaker,,https://cdn.example.com/sneaker-side.jpg,2,Side view
blue-sneaker,,https://cdn.example.com/sneaker-back.jpg,3,Back view
Variant-Specific Images
Use the Variant image URL column to assign images to specific variants. This displays the correct image when customers select that variant option.
Image Hosting Options
Since you need public HTTPS URLs, here's where you can put them:
- Shopify Files: Upload to Content > Files in admin, copy the URLs. Simplest option.
- CDN services: Cloudinary, imgix, etc.
- Your own hosting: Any publicly accessible server works
- Cloud storage: S3 or Google Cloud Storage (make sure public access is configured—this trips people up)
Overwriting vs. Creating Products
That "Overwrite products with matching handles" checkbox? It matters more than you'd think.
- Checked: CSV values replace existing product data for matching handles
- Unchecked: Products with matching handles get skipped entirely
Overwrite Behavior Details
This part has caused me grief before. Here's exactly what happens:
- Blank non-required columns: Existing values get overwritten as blank
- Missing columns: Existing values are preserved
- Columns depending on missing data: Existing data gets deleted
From Shopify: "If a non-required column in the import CSV file is blank, then the matching value in the product list is overwritten as blank."
In practice: if your CSV has a Description column but it's empty for some rows, those products lose their descriptions. Poof. Gone. If you want to preserve existing descriptions, delete the Description column from your CSV entirely.
What CSV Import Can't Do
A few things you can't do through CSV import:
- Delete products (bulk actions in admin only)
- Change product availability on other sales channels
- Cancel an import after you start it
- Import variant metafields—you need the bulk editor or an app for those
- Import 3D models or videos
Customer CSV Import
Customer imports are simpler than products. Fewer columns, fewer ways to mess up.
Required Column
You need an Email column in your CSV. Individual cells can be blank, but the column has to exist. Shopify treats email as the primary customer identifier.
Supported Customer Metafield Types
You can import customer metafields using these types:
boolean- true/false valuesdate- date onlydate_time- date and timenumber_integer- whole numbersnumber_decimal- decimal numberssingle_line_text_field- short text
Password Migration
Can't migrate passwords via CSV. Period. Your customers from the old platform will need to reset their passwords when they first log in. Send them an email about it—otherwise you'll get support tickets.
Multi-Location Inventory Import
If you have multiple locations, inventory gets its own CSV import. It's separate from product data, which can feel redundant but makes sense once you're managing stock across warehouses.
Required Columns
- Handle: Links to the product
- Location: The location name exactly as it appears in Shopify
- SKU or Option1 Name + Option1 Value: Identifies the specific variant
Safety Validation
Shopify compares your "On hand (current)" values against actual inventory. If the numbers don't match—say, some orders came in between your export and import—it'll flag the discrepancy. Helpful for not accidentally wiping out real inventory changes.
Multi-Location Example
Handle,Location,SKU,On hand (current),Incoming,Available
blue-widget,Main Warehouse,BW-001,100,50,100
blue-widget,Retail Store,BW-001,25,0,25
red-widget,Main Warehouse,RW-001,75,25,75
Each location-variant combination requires its own row.
Common Errors and Solutions
You're going to hit at least one of these. Here's what they mean and how to fix them.
Error: "Illegal quoting on line"
Usually means you've got curly/smart quotes instead of straight quotes. Word and Google Docs love to "helpfully" convert these.
Fix it:
- Open the CSV in a text editor (NOT Excel)
- Find and replace curly quotes (" ") with straight quotes (")
- Save with UTF-8 encoding
Error: "Network error: Unexpected token < in JSON at position 0"
This cryptic message usually means your column headers are wrong. Headers are case-sensitive in Shopify.
Download the official template from https://help.shopify.com/csv/product_template.csv and match headers exactly. It's Handle, not handle.
Error: "Daily variant creation limit reached"
You've hit the 1,000 variants/day limit. Only applies to stores with 50,000+ existing variants (and not Shopify Plus).
Split your import across multiple days. Or upgrade, if that's in the budget.
Error: "Validation failed: options are not unique"
You've got duplicate variants—same product with the same option combination appearing twice. Check for duplicate rows or copy-paste errors.
Error: "The uploaded image exceeds the 20 megapixel limit"
Your images are too big. Resize them to under 5000 x 5000 pixels. Honestly, 2048 x 2048 is plenty for most product images.
Error: "Line is invalid (No details)"
The least helpful error message ever. Often happens when you're changing variant option positions on existing products.
Workaround: use temporary option names during import, then fix them through the admin afterward. Annoying, but it works.
General Troubleshooting
My advice: always test with 5-10 products first. Export your current products to see the exact format Shopify expects. And watch for hidden characters—copy-pasting from Word or web pages often brings invisible garbage along.
Metafields in Product CSV
Metafields let you add custom data beyond Shopify's standard fields. The column header format is specific (and a bit ugly).
Column Header Format
<name> (product.metafields.<namespace>.<key>)
Example: Fabric (product.metafields.shopify.fabric)
Supported Metafield Types
- boolean, color, date, date_time, dimension, money
- number_decimal, number_integer
- single_line_text_field, multi_line_text_field, url
- volume, weight
- list.* variants (list.color, list.date, etc.)
- product_reference, list.product_reference
- list.metaobject_reference
One catch: variant metafields don't work through CSV. You'll need Shopify's bulk editor or a third-party app for those.
International Markets Columns
If you're using Shopify Markets for international selling, there are extra columns for market-specific pricing:
| Column | Purpose |
|---|---|
Included / [Primary] | Include in primary market |
Included / International | Include in international markets |
Price / International | Fixed international price (in market currency) |
Compare-at price / International | Fixed compare-at for international |
Replace "International" with your custom market names if configured.
Third-Party Apps: When the Built-In Importer Isn't Enough
Shopify's native CSV import is fine for straightforward cases. But it has real limitations, and sometimes you need something better.
Matrixify (Formerly Excelify)
This is the big one—most popular Shopify import/export app. 4.9/5 stars from 865+ reviews.
| Feature | Native CSV | Matrixify |
|---|---|---|
| File Size Limit | 15 MB | 20 GB |
| File Formats | CSV only | Excel, CSV, Google Sheets |
| Import Progress | No visibility | Real-time progress |
| Cancel Import | Not possible | Yes |
| Multiple Images | Separate rows | Semicolon-separated in one row |
| Metafields | Limited | Full support |
| Variant ID Preservation | No | Yes |
| Multi-Location Inventory | Separate import | Included |
| Scheduled Imports | No | Yes (FTP/SFTP/cloud) |
| Pricing | Free | Free (10 items) to $200/mo |
From one merchant: "We use it daily to update inventory and product information for 17,000 products. If you need to update / import / export big product spreadsheets, this is what you need."
Why people like it:
- Excel files work (formatting stays intact)
- You can actually cancel imports
- Filter what you export—just the products or fields you need
- Preserves product IDs, so collection associations don't break
- Has migration tools for WooCommerce, Magento, BigCommerce
Other Import Apps
EZ Importer - Good for bulk order and draft order imports. More flexible column mapping.
EasyCSV - Stock and price syncing, with automation via FTP, email, or URLs.
GG Simple CSV - Does price and stock updates. Lets you point to a URL for your CSV.
When to Reach for a Third-Party App
- Your file is over 15 MB
- You want to see progress and have the ability to cancel
- You need to preserve variant IDs (for integrations)
- You're scheduling recurring imports from FTP or cloud storage
- Complex metafield structures
- Migrating from WooCommerce, Magento, or similar
Bulk Operations API for Developers
If you're building something custom, Shopify has a GraphQL Admin API for bulk mutations. Not for everyone, but powerful if you need it.
| Feature | Details |
|---|---|
| Concurrent Operations | Up to 5 per shop (API 2026-01+) |
| Time Limit | 24 hours per operation |
| Input Format | JSONL (JSON Lines) |
| File Size | Max 100 MB |
| Rate Limits | Not subject to standard API rate limits |
How It Works
- Create a JSONL file—one mutation input per line
- Upload it using the
stagedUploadsCreatemutation - Run
bulkOperationRunMutation - Monitor via webhook or poll for status
- Download your results
Example JSONL Input
{"input": {"title": "Product 1", "productType": "Snowboard", "vendor": "Vendor1"}}
{"input": {"title": "Product 2", "productType": "Snowboard", "vendor": "Vendor1"}}
Supported mutations include productCreate, productUpdate, productUpdateMedia, and collectionCreate. It's overkill for one-off imports, but if you're building automated pipelines, it's worth knowing about.
A Different Approach: ImportCSV
Both Shopify's built-in importer and the third-party apps work. But they have tradeoffs, and we built ImportCSV to avoid some of them.
File Size Handling
No 15 MB limit. Upload your full catalog and we'll handle the splitting automatically.
Validation Before Import
See your data and catch errors before anything touches Shopify. Missing required fields, broken image URLs, format problems—they're highlighted before you commit.
Column Mapping
Drag and drop to match your columns to Shopify's format. No more renaming headers by hand or getting tripped up by case sensitivity.
Error Recovery
Row-level errors don't kill the whole import. Fix the broken ones and retry just those.
Works Beyond Shopify
Same interface works with Supabase, Firebase, custom APIs. Learn it once, use it everywhere.
Developer-Friendly
If you're building a Shopify app, you can embed ImportCSV as a component. Give your users a decent import experience without building one from scratch.
Wrapping Up
Shopify's CSV imports cover three data types: products (with variants), customers, and inventory. Each has its own columns and quirks.
The quick version:
- 15 MB limit per file
- UTF-8 encoding or you'll get weird errors
- Headers are case-sensitive—match Shopify's format exactly
- Variants: first row gets product details, following rows use the same handle with just variant data
- Images: publicly accessible HTTPS URLs, under 25 megapixels
- Blank cells overwrite existing data; missing columns preserve it
- No cancellation once you start
For bigger catalogs or complex setups, Matrixify is the go-to. For something lighter with validation and visual mapping, ImportCSV is worth a look.
Grab Shopify's official CSV templates:
- Products: https://help.shopify.com/csv/product_template.csv
- Customers: https://help.shopify.com/csv/customer_template.csv
- Inventory: https://help.shopify.com/csv/inventory_template.csv
Want to skip the headaches? Try ImportCSV free and see what validation-first importing looks like.
Wrap-up
CSV imports shouldn't slow you down. ImportCSV aims to expand into your workflow — whether you're building data import flows, handling customer uploads, or processing large datasets.
If that sounds like the kind of tooling you want to use, try ImportCSV .