Key takeaways
- WooCommerce ships with a CSV exporter. It is fine for small catalogues and times out on large ones.
- A truncated export looks identical to a complete one. Always check the row count.
- The Images column contains URLs, not files. Re-host them before the source site goes away.
- If you do not have wp-admin access, storefront extraction is the only route that works.
"Export my products to CSV" sounds like it should be a single click, and for a 40 product store it is. The methods diverge sharply once you have a few thousand products, custom fields, or no admin login.
Here are five approaches, what each one actually produces, and when to reach for it.
Method 1: The built-in WooCommerce exporter
WooCommerce has included a product CSV exporter since 3.1. Go to Products, All Products and click Export at the top of the list table.
You get four controls:
- Which columns to export. Default is all of them. Keep it that way unless you have a specific reason.
- Which product types. Simple, variable, variation, grouped, external. Include variations explicitly if you have variable products, otherwise you export parents with no options.
- Which categories. Multi-select. This is your timeout workaround.
- Custom meta. Tick "Yes, export all custom meta" to capture plugin data and ACF fields. It makes the file much larger and much more useful.
Click Generate CSV and the browser drives the export in AJAX batches.
The failure mode is silent. Because the export runs as a series of browser-driven requests, a PHP timeout or a dropped connection ends the job early and still hands you a downloadable file. Nothing tells you it is incomplete. Open it, count the rows, and compare against the product count in wp-admin every single time.
Best for: catalogues under about 2,000 products where you have admin access.
Method 2: An export plugin
Several paid plugins extend the built-in exporter. What they add:
- Arbitrary filtering, not just category and type.
- Custom column names, so you can hand-build a layout for another platform.
- Chunked processing that survives longer than the built-in exporter.
What they do not solve is the thing that actually costs you time. You still need admin access, you are still bound by your host's PHP limits, and you still have to work out the target schema yourself: which column becomes Shopify's Handle, how variant rows group, where Variant Compare At Price comes from. The plugin gives you a column renamer, not the mapping.
Best for: recurring exports of a store you own, where you have already worked out the column layout once and just want to repeat it.
If the destination is Shopify or WooCommerce specifically, that mapping is a solved problem and you should not be paying for a plugin to hand-roll it. Scrapify writes both schemas directly, which is method 5.
Method 3: WP-CLI
If you have SSH access, this is the most reliable route available to a store owner, because it runs outside the web server and is not subject to request timeouts.
wp wc product list --user=1 --per_page=100 --format=csv > products.csv
The --user flag is required because the WooCommerce CLI acts on behalf of an authenticated user. To include everything rather than the default field subset:
wp wc product list --user=1 --per_page=100 --fields=id,name,sku,price,regular_price,sale_price,stock_quantity,categories,images --format=csv > products.csv
Note that per_page caps at 100 and the command paginates internally, so a large catalogue simply takes longer rather than failing.
Best for: large catalogues, servers you control, anything you want to automate in a cron job.
Method 4: Direct SQL
Products in WooCommerce are posts, so the data lives across wp_posts, wp_postmeta, wp_terms and (on modern versions) the wp_wc_product_meta_lookup table. A minimal query:
SELECT p.ID, p.post_title, p.post_excerpt,
lookup.sku, lookup.min_price, lookup.stock_quantity
FROM wp_posts p
JOIN wp_wc_product_meta_lookup lookup ON lookup.product_id = p.ID
WHERE p.post_type = 'product' AND p.post_status = 'publish';
This is fast and it never times out. It is also the easiest way to get a subtly wrong export, because reconstructing variations, attribute taxonomies and image galleries from raw meta is genuinely fiddly, and any plugin storing data unusually will be missed.
Use SQL for auditing and row counts, where being approximately right is fine. Use one of the other methods for anything you are going to import somewhere else.
Best for: counting, auditing, and pulling a single field across the whole catalogue.
Method 5: Storefront extraction
Every one of the methods above needs credentials. Sometimes you do not have them: you are quoting on a migration, the previous developer has vanished, the client cannot find their login, or the store is simply not yours.
In that case you read what the store already publishes. WooCommerce sites expose product data three ways: the Store API at /wp-json/wc/store/v1/products on most modern installs, JSON-LD structured data in the page head that Google reads, and the rendered page itself.
This is what Scrapify does. Paste a store URL and it detects the platform, reads whichever source is available, and writes a CSV, an Excel file, a Shopify-format file or a WooCommerce-format file. Nothing is installed on the source site and there is no timeout, because the work happens on our infrastructure rather than in your browser.
It is also the fastest route when you do have admin access, because the output is already in the schema you are importing into. The other four methods hand you WooCommerce's own column names and leave the conversion to you.
Best for: exporting into Shopify or WooCommerce format, catalogues large enough to time out the built-in exporter, stores you have no admin access to, supplier and competitor catalogues, and any install too fragile to add a plugin to.
Export any store, no login required
Paste a WooCommerce or Shopify URL and download the catalogue as CSV, Excel, WooCommerce-format or Shopify-format. Free plan, no credit card.
Which one should you use?
| Method | Needs admin | Handles 10k | Writes Shopify / Woo format | Custom fields | Setup | Cost |
|---|---|---|---|---|---|---|
| Built-in exporter | Yes | Unreliably | No | Yes | None | Free |
| Export plugin | Yes | Usually | Hand-mapped | Yes | Install, configure | Paid |
| WP-CLI | SSH | Yes | No | Partial | Shell access | Free |
| Direct SQL | DB access | Yes | No | Manual | Query writing | Free |
| Scrapify | No | Yes | Yes, directly | No | None | Free tier |
The images problem nobody mentions
Every method above puts image URLs in the export, not image files. Those URLs point at the source domain.
This is fine while both sites exist. It becomes a disaster the moment you cancel the old hosting, because your new store's product images all resolve to a dead domain. The failure is delayed by however long you keep paying for hosting you no longer use, which is exactly long enough to have forgotten about it.
Before decommissioning anything, confirm the destination platform has actually pulled the images into its own media library or CDN. In WooCommerce that means checking the media library count. In Shopify it means filtering products by "no image" and expecting zero results.
What to do with the file
Where the export is going determines how much reshaping it needs:
- Back into WooCommerce. No conversion needed. The exporter and importer share a schema. See the WooCommerce CSV schema explained if you plan to edit columns first.
- Into Shopify. Full column rename and row restructure. Start with the WooCommerce to Shopify migration guide.
- Into Google Merchant Center. You want a feed URL rather than a file. See building a Google Shopping feed for WooCommerce.
- Into a spreadsheet for analysis. Open as UTF-8 or your accented characters will arrive mangled.