Exporting data from WordPress does not always require a plugin. If you need posts, users, form submissions, or WooCommerce orders in a spreadsheet, the best method depends on how much data you have and where the export needs to go.
Learn more about professional WordPress development at WPPoland.
If you want the short version first, use plain CSV for most exports, use fputcsv() when building a browser download in PHP, and switch to WP-CLI when the dataset is too large for a normal admin page request.
1. Choose the right export method
There are three common options:
- PHP export inside WordPress for controlled admin-only downloads
- WP-CLI for large datasets and server-side automation
- REST API for external dashboards, integrations, or headless workflows
If the export is occasional and small, a PHP-based download is usually enough. If it is large or recurring, WP-CLI is safer and easier to automate.
2. Export CSV with PHP
For custom exports, CSV is the easiest format to generate.
function wppoland_export_users_csv() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( 'Access denied.' );
}
header( 'Content-Type: text/csv; charset=utf-8' );
header( 'Content-Disposition: attachment; filename=users-export.csv' );
$output = fopen( 'php://output', 'w' );
fputcsv( $output, array( 'ID', 'Email', 'Registered' ) );
$users = get_users(
array(
'fields' => array( 'ID', 'user_email', 'user_registered' ),
'number' => 500,
)
);
foreach ( $users as $user ) {
fputcsv(
$output,
array(
$user->ID,
$user->user_email,
$user->user_registered,
)
);
}
fclose( $output );
exit;
}
This works well for smaller exports or internal tools in the admin area.
3. Use batching for larger exports
The most common mistake is loading too much data into memory at once. Instead, fetch rows in batches.
$offset = 0;
$limit = 500;
do {
$query = new WP_Query(
array(
'post_type' => 'post',
'posts_per_page' => $limit,
'offset' => $offset,
'fields' => 'ids',
)
);
foreach ( $query->posts as $post_id ) {
fputcsv( $output, array( $post_id, get_the_title( $post_id ) ) );
}
$offset += $limit;
} while ( ! empty( $query->posts ) );
Batching reduces memory pressure and helps prevent timeouts.
4. Use WP-CLI for heavy exports
If you are exporting tens of thousands of rows, WP-CLI is usually the better route.
wp post list --post_type=post --fields=ID,post_title,post_date --format=csv > posts.csv
This is especially useful for:
- large WooCommerce order exports
- scheduled nightly exports
- migration and reporting tasks
- internal BI or spreadsheet workflows
5. Use the REST API when another system needs the data
If the data is going to another application instead of a human downloading a file, the REST API is often cleaner than generating CSV in WordPress itself.
Typical cases:
- syncing data to a dashboard
- exporting content into a warehouse or CRM
- triggering structured exports from another service
6. CSV vs Excel
Most WordPress exports should start as CSV:
- easier to generate
- simpler to debug
- works with Excel, Numbers, and Google Sheets
- avoids extra XLSX libraries and memory overhead
If someone explicitly needs .xlsx, it is often better to convert the CSV after export rather than making WordPress generate a heavier spreadsheet format directly.
Summary
- Use PHP +
fputcsv()for smaller custom exports. - Use batching when the dataset grows.
- Use WP-CLI for large or recurring exports.
- Use the REST API when another system needs structured data.
- Prefer CSV first, then convert to Excel only if necessary.



