How to Export WooCommerce Orders to CSV

To export WooCommerce orders as a CSV you have 3 working routes, and the one most tutorials name does not exist. WooCommerce 11.0.1 has no order export sitting in Status > Tools. What it does have is a Download button on the Analytics Orders report, a free plugin called Advanced Order Export for WooCommerce that adds real field and filter control, and a WP-CLI command, wp wc shop_order list, on any store with shell access.

There are two ways store owners lose an afternoon here. The first hunts through Status > Tools for a core CSV export, finds transient clearing and thumbnail regeneration instead, and decides WooCommerce is broken. The second installs the top-rated export plugin, spends 20 minutes wiring a Monday-morning scheduled delivery, then hits the save button and learns that scheduling was never in the free build.

Pick the method by whether the export has to repeat, not by how many orders you have.

The 3 Ways to Export WooCommerce Orders

WooCommerce 11.0.1 is the current stable release, last updated on August 10, 2026, running on more than 7 million active installations. None of them have a core order CSV export in the Tools screen. Status > Tools is a maintenance panel: clear transients, regenerate thumbnails, recount terms, delete orphaned variations. WooCommerce’s own documentation on importing and exporting orders points store owners at a paid extension rather than a built-in feature.

Wrong screen.

Here is what actually exists, and what each route can and cannot control.

MethodWhere It RunsField ControlFilteringSchedulingCost
WooCommerce Analyticswp-admin, Analytics > OrdersFixed report columnsDate range, plus whichever statuses Analytics is set to trackNoIncluded in WooCommerce
Advanced Order Export for WooCommercewp-admin, WooCommerce > Export OrdersEvery field, including order metaDate, status, product, customer, payment methodPro onlyFree, Pro from $30/year
WP-CLIServer shell over SSHAny field the REST API returnsAny parameter the REST API acceptsYes, via server cronFree, needs SSH access

Read that table by its last two columns. If the export has to repeat without a human clicking a button, the free plugin drops out and the real choice is between the Pro license and a cron entry.

Export WooCommerce Orders From Analytics

The genuine built-in export lives at WooCommerce > Analytics > Orders. Set the date range and any filters at the top of the report, then use the Download button in the upper right corner of the table header. It behaves differently depending on how much data you asked for, which is the detail nobody mentions.

  • A report that fits on one screen downloads as a CSV straight away.
  • A report spanning more than one page is queued as a background job, and WooCommerce emails a download link to the address attached to your WordPress account.
  • The columns are the report’s columns. No field picker, no custom order meta, no rename or reorder.
  • Analytics counts Processing, On hold, and Completed by default. Pending payment, Cancelled, and Failed are excluded until you add them under Analytics settings.
  • Refunded cannot be excluded, whatever else you change.

That status default is the part that bites. An accountant asking for “all January orders” and a WooCommerce Analytics CSV covering January are not the same file, and nothing on screen tells you a cancelled order was left out. The rules are documented in the WooCommerce Analytics reference, and they are worth reading once before anyone downstream builds a reconciliation on top of the file.

Check the status list before you send that CSV to anyone.

Export WooCommerce Orders With Advanced Order Export

Advanced Order Export for WooCommerce, from algol.plus, is where most stores end up. It is free on WordPress.org with 100,000+ active installations, and version 4.1.0 landed on June 8, 2026. Install, activate, and a new panel appears under WooCommerce > Export Orders.

What the free build gives you:

  • Output as CSV, Excel, XML, JSON, PDF, or HTML.
  • Field selection across order, customer, product, and coupon data.
  • Renamed column labels and custom column order, so the file matches what the receiving system expects.
  • Custom fields and taxonomies, which is the reason most stores install it.
  • Grouping by product or by customer.
  • Bulk export straight from the orders list screen, for a handful of selected orders.

Filters That Change the Output

The filter panel is where the plugin earns its place over the Analytics download. Date range takes explicit from and to dates or relative windows, so a monthly bookkeeping pull becomes one saved setting. Order status is a checkbox list of every WooCommerce status, including the ones Analytics hides by default. Product and category filters narrow the file to orders containing a specific SKU, which is the export a supplier actually wants. Customer filters work on user IDs, roles, or billing country, which is how a tax jurisdiction export gets built. Payment method filters let you pull only Stripe or only PayPal rows to match against one processor’s statement.

Each of those becomes a saved profile you reuse instead of rebuilding.

One Row Per Order vs One Row Per Product

This is the setting that quietly decides whether the file is usable. Both options live under the plugin’s format settings.

One row per order: every line item is collapsed into a single cell, separated by a delimiter. One row per product: each line item gets its own row and the order header repeats down the block.

Accounting tools that import invoice lines want one row per product, because they read line items and not order headers. Dashboards and shipping tools usually want one row per order, because they aggregate at the order level and a repeated header inflates every count. Pick the wrong one and the import either fails loudly or, worse, succeeds with triple the revenue.

Ask first.

Scheduling Is a Pro Feature

The free version exports on demand. A person opens the panel, picks a profile, clicks Export. That is the whole loop, and it does not run itself.

WordPress.org lists “Export orders on a flexible schedule” under the plugin’s pro features, alongside exporting a single order right after a status change and delivering the file to email, FTP, or an API endpoint. If your plan was an automated CSV waiting in the inbox on Monday, that plan needs a license.

Pro only.

Pricing on the official AlgolPlus download page runs $30 a year for 1 site, $50 for 2, $120 for 5, and $180 for 10, each with a year of updates. Unlimited-update variants sit at $120, $180, and $350. There is a 30-day money-back window. Against a bookkeeper billing hourly to assemble the same file by hand, the 1-site tier pays for itself inside a month, which is the only comparison that matters.

Export WooCommerce Orders With WP-CLI

WooCommerce has shipped WP-CLI support since version 3.0.0. The WC_CLI_REST_Command class generates a CLI subcommand for every WooCommerce REST endpoint, and that is exactly where wp wc shop_order list comes from. It is not a bespoke export command, which explains most of its behavior. If the rest of the toolset is unfamiliar, our WP-CLI cheat sheet covers the commands worth memorizing first.

The Base Command

wp wc shop_order list --user=1 --per_page=100 --format=csv > orders.csv

Every flag in that line does a specific job:

  • --user=1 authenticates as that user ID. The WooCommerce CLI commands run through the REST layer, so they need a user with permission to read orders.
  • --per_page=100 sets the page size. The orders endpoint defaults to 10, and the WordPress REST collection schema caps the value at 100.
  • --format=csv writes CSV. The alternatives are table, json, yaml, ids, and count.
  • The redirect sends output to a file instead of the terminal.

One call returns one page, and nothing in the REST reference promises otherwise. To pull a full store you walk the pages yourself with --page, which means stripping the repeated header row afterward:

wp wc shop_order list --user=1 --format=count
for p in $(seq 1 12); do
  wp wc shop_order list --user=1 --per_page=100 --page=$p --format=csv | tail -n +2
done > orders.csv

Run the count first, divide by 100, and set the loop bound from the answer instead of guessing. The tail call drops each page’s header line, so you prepend one header manually or let the import step skip it.

Count, then loop.

Filtering by Date and Status

The REST API documents after and before as limiting the response to resources published after or before a given ISO8601 date. Published means created. It is not the modified date, and treating it as one is how a month-end reconciliation goes sideways.

wp wc shop_order list --user=1 --per_page=100 \
  --after=2026-07-01T00:00:00 --before=2026-08-01T00:00:00 \
  --format=csv > july-orders.csv

An order created on July 31 and refunded on August 3 lands in the July file, because creation is what the filter reads. If your accountant works on the date money moved rather than the date the order was placed, this command is answering a different question than the one they asked.

Creation, not modification.

wp wc shop_order list --user=1 --per_page=100 --status=completed --format=csv > completed.csv
wp wc shop_order list --user=1 --per_page=100 --fields=id,status,total,date_created,billing --format=csv > summary.csv

The --fields flag takes any field the orders endpoint returns. Nested ones such as billing, shipping, and line_items come back as a JSON string inside a single cell, which is fine for a script and painful for a human.

Scheduling With Cron

Once the command is right, a crontab entry turns it into the automation the free plugin cannot do:

0 2 * * 1 cd /var/www/example.com && wp wc shop_order list --user=1 --per_page=100 --after=$(date -d '7 days ago' +\%Y-\%m-\%d) --format=csv > /backups/orders-$(date +\%Y-\%m-\%d).csv

That runs at 2 AM every Monday, pulls the previous 7 days, and writes a dated file. The backslashes before each % are not decoration: cron treats a bare percent sign as a newline and will silently truncate the command without them. Pair it with rclone or aws s3 cp if the file needs to leave the server.

WP-CLI needs shell access, so confirm your host provides SSH before you design a pipeline around it. Most managed WordPress hosts include it as standard. Treat a production store the same way you would treat a WP-CLI search-replace on a live database: read-only commands like this one are safe, but the habit of checking before you run is the thing worth keeping.

HPOS and Where Orders Actually Live

High-Performance Order Storage went stable and became the default for new installations in WooCommerce 8.2, released in October 2023. Orders moved out of wp_posts and wp_postmeta into four dedicated tables: wc_orders, wc_order_addresses, wc_order_operational_data, and wc_orders_meta.

WP-CLI reads orders through the REST layer, so it follows whichever storage the store is using and needs no adjustment. The things that break are custom reports and legacy plugins that query wp_posts for a shop_order post type directly. They do not error. They return zero rows, which looks exactly like a quiet week.

CSV Formatting Problems That Break the File

Most export complaints are not export bugs. They are what a spreadsheet does to a correct file the moment you open it.

Leading zeros disappear. An order number stored as 00123 opens as 123 because Excel reads the cell as a number. Import through Data > From Text/CSV and set that column to Text before the data lands, or open the file in Google Sheets, which preserves the string.

Long numbers lose their tail. Excel carries a maximum precision of 15 significant digits and rounds everything past the 15th down to zero, so a 19-digit transaction ID comes back subtly wrong rather than obviously broken. Microsoft’s own guidance is to format the column as Text before the number is entered, or prefix the value with an apostrophe.

Format as text.

Accented names turn to mojibake. Excel needs a byte order mark to recognize a file as UTF-8; without one it falls back to the system codepage and Müller becomes garbage. Advanced Order Export has the switch, labelled “Output UTF-8 BOM” rather than anything shorter, which is why searching the settings panel for “BOM” alone finds nothing. Google Sheets does not need it.

Nested fields arrive as JSON. A WP-CLI export of line_items writes [{"id":1,"name":"Product"}] into one cell. Parse it with Power Query or a script. Reading it by eye across 4,000 rows is not a plan.

ISO dates sort as text. The REST API uses ISO8601 throughout, so a value like 2026-07-14T10:23:45 arrives correct and sorts alphabetically until you convert the column to a date type. Convert on import rather than changing the export format, because regional date strings break every system downstream.

Exporting Custom Checkout Fields

Fields added by Checkout Field Editor, Flexible Checkout Fields, or ACF are stored as order meta, and that is what decides whether a method can reach them.

  • The Analytics download cannot see them at all. Its columns are fixed report columns.
  • Advanced Order Export lists every meta key in the field panel. Tick the keys you want and they become columns.
  • WP-CLI returns them through --fields=meta_data as a serialized structure that needs post-processing before anyone can read it.

If the fields exist because someone added a VAT number, a delivery window, or a purchase order reference to the form, the plugin is the only route that produces a file a human can open. Worth saying plainly: every extra checkout field is also a conversion cost, and checkout optimization usually argues for collecting fewer of them, not exporting more.

The Limits

None of these 3 methods produces a finished accounting record. Each stops somewhere specific.

  • The Analytics export cannot include order meta, so a store collecting anything custom at checkout will never get it out this way. You still have to install a plugin or write a query.
  • The Analytics export reflects Analytics settings, not the orders table. A file described as “all orders” is a file of the statuses that report is configured to count, and you have to state that when you hand it over.
  • The free plugin cannot run unattended. Somebody clicks Export every time, so a weekly report is a weekly person, not a weekly automation.
  • WP-CLI returns 100 rows per call at most, and the loop, the header stripping, and the page count are all yours to write and maintain.
  • No method reconciles a refund against the order it belongs to. A refund is separate data, so partial refunds and chargebacks stay a manual join in whatever tool receives the file.

What Quietly Ruins an Order Export

Sending the file the moment it downloads. It feels like fast service to the bookkeeper. It costs you the four rounds of “this doesn’t match” that follow, because nobody agreed which statuses and which date field the file was built on.

Choosing “one row per order” for an accounting handoff. The file looks tidier, one line per sale. Then the import reads a pipe-separated cell as a single product and every line-item total in the ledger is wrong.

Double-clicking the CSV to check it looks fine. Excel silently reformats leading zeros, long IDs, and dates during that preview, and if anyone saves the file at that point the damage is now the file. Open through the import dialog every time, even for a glance.

Skipping the BOM because the test rows were English. Accented customer names sit further down the file where nobody scrolled, so the problem surfaces in the client’s inbox rather than yours.

Building a custom report query against wp_posts on a store that runs HPOS. It fails silently by returning nothing, and empty output reads like a slow month rather than a broken query.

Automating the export before anyone has confirmed the columns. You end up with 12 weeks of a perfectly scheduled file that nobody can use, which is more expensive than 12 manual exports would have been.

FAQs on Exporting WooCommerce Orders

Does WooCommerce Have a Built-In Order Export?

Yes, but not where most guides say. It is the Download button on the Analytics Orders report, not an entry in Status > Tools. It produces a CSV of the report’s columns for the range and statuses Analytics is configured to show.

Can I Export WooCommerce Orders by Date Range?

All 3 methods handle date ranges. Analytics uses the report’s date picker, Advanced Order Export has explicit and relative date filters, and WP-CLI takes --after and --before. The CLI flags filter on the order’s creation date.

Can I Schedule WooCommerce Order Exports to Email?

Not with the free version of Advanced Order Export. Scheduled exports and email, FTP, or API delivery are listed as pro features, starting at $30 a year for a single site. The free alternative is a server cron entry running WP-CLI.

Why Does My Export Fail on a Large Store?

Admin-side exports run inside a PHP request and hit memory or execution limits. The Analytics report sidesteps this by queuing multi-page downloads as a background job and emailing a link. For very large stores, WP-CLI avoids the web request entirely.

Does HPOS Change How Exports Work?

Not for these 3 methods. Analytics, Advanced Order Export, and WP-CLI all read orders through WooCommerce’s own data layer, so they follow the storage in use. Custom code that queries wp_posts for orders is what breaks after the switch.

Final Remarks

The hard part of an order export was never the export. It is agreeing what the file means before anyone builds on it: which statuses count, which date the rows are keyed on, whether a row is an order or a line item. Get those 3 answers written down and any of the methods here will produce the file. Skip them and you will produce several files, all correct, none matching.

The honest trade is between a $30 license and a cron entry you own. The license buys scheduling you never maintain; the cron entry costs an afternoon and never renews.

Decide which one you would rather still be running in 3 years.

Continue reading: WordPress REST API · Ecommerce Checkout Optimization · Product Schema Markup

Tell Google you want more of this.

Add Gatilab as a preferred source

One tap, and this site shows up more often in your own Top Stories, AI Overviews and AI Mode. Remove it any time.