WooCommerce ships with a CSV importer and in 90% of cases that is all you need - provided the file has columns the store understands. No 200 PLN a year plugin, no developer. What you do need is to know what a valid file looks like, because the whole difficulty of a bulk import sits in preparing the spreadsheet, not in clicking around the admin.
This piece is about the situation where the source of the products is your own spreadsheet: a migration from another platform, a manufacturer’s catalogue in Excel, a bulk price change, or an export before a rebuild. If the source is a supplier feed that refreshes every day, that is a different job and I covered it separately in the piece on importing products from a supplier XML feed - there the schedule, the product key and category mapping are what matter, not a one-off upload.
The built-in importer - where it is and what it does
You will find it under Products → All Products → Import. The same screen has an Export button. Both are part of WooCommerce itself, not a plugin, and both work on CSV files.
The importer does three things:
- Creates new products from rows that are not in the catalogue yet
- Updates existing ones, if you tick the relevant checkbox and it can match the product by ID or SKU
- Maps columns - in the second step it lists your headers and lets you assign each one to a WooCommerce field
What it does not do: it will not delete products missing from the file, it will not import orders or customers, it will not read XML, and it cannot fetch anything from a URL on a schedule. Those need a plugin.
Before you click Import: back up the database. An import is a bulk operation and undoing it by hand across 800 products is not realistic. How to make a backup that actually restores I described in a separate piece.
The columns WooCommerce understands
The shortest route to a valid file: export a handful of products you already have first. You get a CSV with the correct headers and a live example of how the store writes prices, categories and attributes. That file becomes your template - delete the rows, keep the header, paste your own data in.
The columns that do most of the work in practice:
| Column | What it holds | The trap |
|---|---|---|
ID | the product number in the store | leave empty for new products |
SKU | your product code | must be unique or the import stops |
Type | simple, variable, variation, grouped, external | empty means simple product |
Regular price | base price | decimal point, not a comma |
Sale price | discounted price | an empty column wipes sales on update |
Categories | categories | hierarchy with >, several separated by commas |
Images | image addresses | full URLs, comma separated, first one is the main image |
In stock? | 1 or 0 | mixing it up with Stock is the classic |
Stock | quantity | only works with stock management on |
Attribute 1 name / value(s) | attribute name and values | values separated by commas |
A category written as Garden > Furniture > Chairs creates the whole path if it does not exist. A price written as 129,90 with a comma is read as 129 - that is the single most common reason for “why are my prices wrong after the import”.
Images from URLs: WooCommerce downloads them onto your server during the import. At 500 products with three images each that is 1,500 downloads in one run, and it is the most common place for an import to hang. If you have the images locally, upload them to the media library first and point the file at addresses on your own domain - it runs several times faster.
File encoding, or where the question marks come from
This gets its own section because it eats more of other people’s time than anything else. WooCommerce expects UTF-8. Excel, depending on your regional settings, saves plain CSV in a local code page instead - so after the import you get mangled characters across 300 products at once. Anything outside plain English is at risk: accents, umlauts, Polish diacritics.
Three ways to avoid it:
- In Excel choose Save As → CSV UTF-8 (Comma delimited), not plain CSV
- Work in Google Sheets and download as CSV - it writes UTF-8 by default
- Check the file before importing: open it in a plain text editor and see whether the special characters look right
The related setting is the delimiter. The default is a comma; if your spreadsheet uses semicolons, set that under Advanced options in the first step of the import instead of rewriting the file.
Variations in CSV - where imports break most often
A product with sizes and colours takes up several rows in the file: one for the parent product and one for each combination.
The parent row:
Type=variableAttribute 1 name=Size,Attribute 1 value(s)=S, M, LAttribute 1 global=1if you use an attribute defined globally in the store- Price stays empty - the price belongs to the variation, not the parent
The variation rows:
Type=variationParent=id:followed by the parent’sSKUorIDvalue from the same fileAttribute 1 value(s)= a single value, for exampleM- Its own
SKU,Regular priceandStock
Three mistakes I see in these files constantly: a variation pointing at a parent that is neither in the file nor in the store; an attribute value in the variation differing from the parent’s even by capitalisation; a parent with a price filled in, so the store shows that instead of the variation prices. All three produce the same symptom - the product exists but cannot be bought.
Order matters too: the parent has to appear in the file before its variations.
Updating instead of duplicating
The “Update existing products” checkbox in the first step decides everything. Unticked, every row creates a new product even if an identical one already exists. Ticked, WooCommerce looks for a match first by ID, then by SKU.
Which gives you the practical rule: SKU is the key to your catalogue. If products have no SKU, or duplicate SKUs, a bulk update has nothing to latch onto and you end up with two copies of the same stock.
The second thing worth knowing: on update the importer overwrites the columns present in the file and leaves the rest alone. That is extremely useful. Want to change just the prices on 600 products? Build a file with two columns - SKU and Regular price - and upload it with update ticked. Descriptions, images and stock levels stay untouched.
Watch the inverse: a column that is present but empty clears the field in the store. An empty Sale price column wipes every sale you have running. If you are not changing something, simply leave that column out of the file.
Large files and server limits
The importer processes the file in batches and comes back for the next portion by itself, so formally there is no size limit. In practice your PHP settings are the ceiling:
upload_max_filesize- a bigger file will not be accepted by the form; the workaround is to upload the CSV over FTP and use the import-from-server optionmax_execution_time- too short and a batch dies halfway throughmemory_limit- with long descriptions and many attributes, 128 MB can fall short
The symptom is identical for all three: the import stops at, say, 40% and goes no further. Rather than guessing, split the file into batches of 300-500 rows and run them in sequence. On a new server I start every first import with a 10-row sample anyway - a minute tells you whether the column mapping is right, before every product goes in.
If the store chokes on operations like this routinely, the problem is the hosting rather than the file - I set that out in the piece on WooCommerce hosting requirements.
Export - what it is actually good for
The exporter has four settings: which columns to export, which product types, which categories, and whether to include custom meta (fields added by plugins). The output is a CSV download.
Four uses I reach for most:
- Bulk editing in a spreadsheet. Export → edit in Excel or Sheets → import with update. Faster than clicking, and you see the whole catalogue at once
- A template for a new file. Headers and value formats already correct, no guessing
- A snapshot before a big change. A database backup matters more, but a CSV of pre-migration prices is a useful reference point; during a platform move it pairs with the migration without losing rankings checklist
- Handing the catalogue to someone else. Accounting, a marketplace, a price comparison site
What the exporter does not cover: orders, customers, coupons and reviews. Core WooCommerce has no order export - that needs a plugin or an integration. If what you actually want is orders flowing between systems, that is not a CSV job but a case for stock and order synchronisation.
When the native importer stops being enough
The line is reasonably clear. The built-in importer covers one-off and occasional operations on your own file. You need more when:
- The source is XML or an API, not CSV
- The import has to run automatically at a set time, with nobody clicking
- Data has to be transformed on the way in: add a markup, convert a currency, build a description out of several fields, skip products below a stock threshold
- Products missing from the new file have to be removed
- The source columns get renamed with every delivery and the mapping has to survive the mess
That is when you use a scheduled import tool or write an integration. When that pays for itself, and what the arrangement looks like with an ongoing supplier, I covered in the pieces on dropshipping and supplier integration and on XML feed imports.
The order of operations that saves you an evening
The working procedure I stick to on every larger import:
- Back up the database and files
- Export 5 existing products as a header template
- Prepare the file in UTF-8, prices with a decimal point, SKUs unique
- Import a 10-row sample with update unticked
- Check in the store: price, category, image, availability, how the product page looks
- Delete the sample products
- Import the rest, in batches of 300-500 rows for larger catalogues
- Check the product count in the admin and open 10 random product pages
- Clear the cache so the new prices actually appear on the front end
Steps 4 and 5 are the ones people skip, and they are the ones that cost the most later.
Frequently asked questions
How do I import products into WooCommerce from an Excel file?
Save the spreadsheet as CSV in UTF-8, then go to Products → Import. Excel’s .xlsx format is not supported directly - the importer only takes CSV. In the second step map your headers to WooCommerce fields; if you named the columns the way the store’s own export does, the mapping fills itself in.
Why do I have duplicate products after importing? Because “Update existing products” was not ticked, or the products have no SKU for the importer to match on. The rule: without a unique SKU, every further import creates new products. Duplicates can be removed in bulk by filtering the product list by the date they were added.
Can I import products with variations?
Yes, but each variation is its own row with type variation and the parent named in the Parent column. The parent has to appear earlier in the file than its variations, carry type variable and an empty price, and the attribute values must be written identically on the parent and on the variations.
How do I change all my prices at once?
Export the catalogue, keep only the SKU and Regular price columns, recalculate in the spreadsheet and import the file with “update existing products” ticked. Everything else stays untouched, because the importer only overwrites columns that are present in the file.
Will importing slow the store down? While it runs, yes - the server is processing data and downloading images. That is why I run larger imports outside peak hours and split them into batches. Afterwards there is no effect on speed, unless you uploaded photos straight off a camera, in which case the problem is not the products but their weight.
Running a store where something does not work the way it should? I build and rebuild WooCommerce stores - from a single fix to reworking the whole sales flow. Tell me what you are dealing with and I will send back a scope and a price.