How to Export WordPress Posts to CSV (4 Ways)

Sooner or later, someone asks for your WordPress content as a spreadsheet. Not a backup, not a staging clone — an actual list of posts with titles, dates, statuses, authors and URLs that a human can sort, filter and colour-code. Maybe it’s a content audit, maybe it’s a translator quoting on word count, maybe it’s a client who thinks in rows and columns. Whatever the reason, you need to export WordPress posts to CSV, and WordPress core doesn’t have a button for it.
First, a clarification that saves a lot of wasted clicks. This guide is about exporting posts and pages — your content. It is not about exporting form entries (contact form submissions, leads, survey responses). Those live in completely different database tables, are handled by completely different plugins, and need a completely different export route. If entries are what you’re after, our guide to storing and exporting WordPress form entries is the one you want. Still here? Good — let’s get your content into a spreadsheet.
Why export posts to CSV in the first place
Four situations account for almost every request we see:
- Content audits. You can’t decide what to prune, merge or refresh until you can see everything in one view. A CSV of every post with its date, status, author, category and URL is the raw material for a proper WordPress content audit — drop in traffic data from Analytics or Search Console and you have a decision table.
- Migrations and re-platforming. Moving to a different CMS, a headless setup, or a static site generator? Those tools rarely read WordPress’s native export format, but nearly all of them read CSV.
- Bulk editing in a spreadsheet. Rewriting 300 meta descriptions or fixing a naming convention across a category is miserable in the admin and pleasant in a spreadsheet — export, edit the column, re-import with an import plugin.
- Handing content to someone else. Clients, translators, legal reviewers and agencies all want a file, not a login. CSV is the lowest common denominator that everyone can open.
Four routes get you there. They differ mainly in whether you need a plugin, whether the full post body comes along, and whether custom fields are included.
Method 1: The built-in Tools → Export (with an honest caveat)
Every WordPress site has an export screen at Tools → Export. You pick All content, or narrow it to Posts, Pages, Media or a custom post type, optionally filter by category, author, date range and status, then click Download Export File.
Here’s the caveat that sends most people to Google in the first place: this does not produce a CSV. It produces a WXR file — WordPress eXtended RSS — which is XML with a .xml extension. Open it in a spreadsheet app and you’ll get a wall of markup, not columns.
That’s not a flaw, it’s a different job. WXR is designed for WordPress-to-WordPress moves: it preserves post content, excerpts, slugs, publish dates, authors, categories, tags, custom fields and comments, and the WordPress Importer on the receiving site reconstructs all of it faithfully. No CSV format can do that as cleanly, because CSV has no concept of nested or repeating data.
So: use Tools → Export when the destination is another WordPress site. Use one of the next three methods when the destination is a spreadsheet, a human, or a non-WordPress system. Converting WXR to CSV afterwards is technically possible with a script or online converter, but it’s more work than just exporting to CSV directly.
Method 2: A CSV export plugin
The most common answer, and the right one for most non-technical users. Several export plugins exist in the WordPress.org directory and the commercial market (WP All Export is the best-known; there are lighter free alternatives). We’re describing the general capability rather than walking through one plugin’s exact screens, because these interfaces change often — check the current docs of whichever you install.
What a decent CSV export plugin gives you:
- Column selection. Choose exactly which fields become columns — ID, title, slug, date, modified date, status, author, permalink, excerpt, and the full
post_contentif you want it. - Post meta / custom fields. This is the big one. SEO titles and meta descriptions, ACF fields, WooCommerce product attributes — these live in
wp_postmetaand a good exporter lets you map any meta key to its own column. - Taxonomies. Categories and tags flattened into a column, usually comma- or pipe-separated. Watch the separator if your terms contain commas.
- Filtering. By post type, status, date range, author, or taxonomy term — so you can export “published posts in Tutorials from 2025” rather than everything.
- Round-tripping. The better tools pair with an importer, so you can export, bulk-edit in a spreadsheet, and re-import updates matched on post ID. Always test that loop on staging first.
Trade-offs: it’s another plugin on the site, big exports can time out on cheap shared hosting (look for a batching or chunking option), and the more capable tools are commercial. For a one-off export, install, export, deactivate.
Method 3: WP-CLI (fastest, no plugin needed)
If you have SSH access, this is the cleanest option — no plugin, no timeout, and repeatable. WP-CLI’s wp post list command speaks CSV natively.
The core command, run from your WordPress root directory:
wp post list --post_type=post --fields=ID,post_title,post_date,post_status --format=csv > posts.csv
That gives you one row per post with just those four columns. A few useful variations:
- All posts, not just the first batch. Add
--posts_per_page=-1to lift the default query limit on large sites. - Pages instead of posts.
--post_type=page, or a custom post type slug, or a comma-separated list like--post_type=post,page. - Only published items.
--post_status=publish(default behaviour varies, so it’s worth being explicit). - More columns.
--fields=ID,post_title,post_name,post_date,post_modified,post_author,post_status. Addpost_contentif you truly want the body text in a cell — see the caveats below before you do. - Filter by meta.
wp post listpasses unrecognised arguments through toWP_Query, so--meta_key=_thumbnail_id --meta_compare=NOT EXISTSfinds posts missing a featured image.
Getting custom field values into the same CSV is where WP-CLI gets fiddly: wp post list exports post table columns, while meta lives behind wp post meta list <id>, which is per-post. The usual pattern is to export IDs first, then loop:
for id in $(wp post list --post_type=post --field=ID); do wp post meta get $id _yoast_wpseo_metadesc; done
Note --field=ID (singular) returns a bare list of values, which is what makes it loopable. For anything more elaborate than a couple of meta keys, a plugin from Method 2 will be less work than shell plumbing.
Running it over SSH
Connect with ssh [email protected], change into the WordPress root (cd /var/www/yoursite or wherever wp-config.php lives), and run the command. The file lands on the server, so pull it down from your local machine with scp [email protected]:/var/www/yoursite/posts.csv . — or, if your host offers WP-CLI through a web terminal, just download it via SFTP. Managed hosts including Kinsta, WP Engine, SiteGround and Cloudways all ship WP-CLI; check your host’s docs for the exact SSH details.
Method 4: A quick SQL export via phpMyAdmin
For read-only reporting, when you want a specific slice fast and nobody needs to re-import it, a direct database query is the bluntest and quickest instrument. In phpMyAdmin (or Adminer, or the mysql CLI), run something like:
SELECT ID, post_title, post_date, post_status FROM wp_posts WHERE post_type='post' AND post_status='publish' ORDER BY post_date DESC;
Then use phpMyAdmin’s Export button on the result set and choose CSV. Substitute your real table prefix — wp_ is only the default.
Now the warnings, because they matter. Only ever run SELECT statements here. A stray UPDATE or DELETE against a live database has no undo, and phpMyAdmin will not ask twice. Take a database backup before you go anywhere near it. Raw SQL also bypasses WordPress entirely, so you get raw stored values: no filters applied, no shortcodes rendered, permalinks not resolved, and revisions and auto-drafts included unless you exclude them. It’s a reporting shortcut, not a content pipeline.
Comparing the four methods
| Method | Needs a plugin? | Includes content body? | Includes post meta? | Best for |
|---|---|---|---|---|
| Tools → Export (WXR) | No | Yes | Yes | WordPress-to-WordPress moves — but output is XML, not CSV |
| CSV export plugin | Yes | Optional | Yes, mappable | Non-technical users; custom fields; export-edit-reimport |
| WP-CLI | No | Optional | Awkward (per-post) | Fast, repeatable exports with SSH access |
| SQL / phpMyAdmin | No | Optional | Needs a JOIN | One-off read-only reporting slices |
Practical gotchas nobody mentions until it’s too late
Encoding: UTF-8 and Excel don’t get along by default
Your export is UTF-8. Excel, on Windows, often assumes the local ANSI codepage instead — so curly quotes, em dashes, accented names and emoji turn into ’ and friends. Two fixes: open the file via Excel’s Data → From Text/CSV importer and set the origin to UTF-8, or save the file with a UTF-8 BOM so Excel detects it automatically. Google Sheets and LibreOffice handle plain UTF-8 correctly without the ceremony.
Commas and line breaks inside post_content
This is the number-one reason a “broken” CSV has columns sliding sideways. Post bodies are full of commas, double quotes, and newlines, and every one of them is a CSV delimiter waiting to happen. Properly written exporters quote and escape fields, and properly written parsers handle quoted newlines — but naive scripts on either end do not. Our advice: leave post_content out unless you genuinely need it. Export IDs, titles and metadata for auditing; keep the bodies in WordPress. If you must include content, verify the row count in your spreadsheet matches the post count before trusting anything downstream.
Other things to sanity-check
- Leading
=,+or-in a title makes Excel treat the cell as a formula. Rare, but it looks like data loss when it happens. - Revisions and drafts quietly inflate exports if you don’t filter by status.
- Serialized meta (arrays stored by ACF and similar) exports as unreadable
a:2:{...}strings. Flatten it in the exporter or accept it’s for machines only.
A CSV export is not a backup
Say it out loud before you delete anything. A CSV holds the columns you selected — not media files, not theme or plugin settings, not users, comments, taxonomy structures or the relationships between them. You cannot rebuild a site from it. Use a real backup plugin or your host’s snapshots for backups, and treat CSV as what it is: a reporting and interchange format.
Rule of thumb: moving to another WordPress site? Tools → Export. Building a spreadsheet for humans? WP-CLI if you have SSH, a CSV export plugin if you don’t. Touching the database directly is a last resort, and always with a backup in hand.
One aside, clearly labelled: if you arrived here wanting form submissions rather than posts, that’s a genuinely different export and none of the above will help. Our own free EntryVault plugin (disclosure: we make it) does CSV export and import for entries from 11 form builders — it does not export posts or pages, so it’s only relevant if you’re in the wrong guide.
Frequently asked questions
Does WordPress have a built-in CSV export for posts?
No. The built-in Tools → Export produces a WXR file, which is XML designed for moving content between WordPress sites — not a CSV. To get a spreadsheet you need a CSV export plugin, WP-CLI’s wp post list --format=csv command, or a direct SQL query exported from phpMyAdmin.
How do I export WordPress posts to CSV using WP-CLI?
Run wp post list --post_type=post --fields=ID,post_title,post_date,post_status --format=csv > posts.csv from your WordPress root directory over SSH. Add --posts_per_page=-1 to include every post, adjust --fields for the columns you want, and download the resulting file with scp or SFTP.
Why does my exported CSV look broken in Excel?
Usually one of two things: Excel misreading UTF-8 characters, which you fix by importing via Data → From Text/CSV and setting the origin to UTF-8, or unescaped commas and line breaks inside post content pushing data into the wrong columns. Leaving the post_content field out of the export avoids the second problem entirely.
The bottom line
Exporting WordPress posts to CSV is easy once you stop expecting core to do it. Tools → Export is for WordPress-to-WordPress moves and hands you XML; for an actual spreadsheet, reach for WP-CLI if you have SSH, a CSV export plugin if you don’t, and SQL only for quick read-only slices. Keep post bodies out of the file unless you need them, mind the UTF-8 handshake with Excel, and never mistake the result for a backup.