I have over 20 thousand pages and need to delete all of them except very few. Deleting them from the wp-admin page would take too long and a huge effort. Is there a command I can run in PhpMyAdmin to do the job?

let's assume that I want to keep pages with ID (1,2,3) and delete the rest.

Thanks a lot.

  • That would be SQL, which is off topic here. – vancoder Jun 8 at 22:13
  • Where to ask this question, please? – shireef khatab Jun 8 at 22:19
  • 1
    I'd use wp-cli post delete instead, since that delete things properly, tidying up comments etc. too. You can run this in batches with lots of post numbers, and use wp post list to fetch back the IDs to delete, and grep -v to filter out the ones you want to keep. – Rup Jun 8 at 23:47
  • Definitely a use case for which wp-cli was designed. – jdm2112 Jun 9 at 1:49
  • @ Rup, @ jdm2112: How can I achieve that via wp-cli, please? can you give all commands required as I'm not too good at it? Thanks a lot, by the way, I can delete permanently with no problem including all posts too. – shireef khatab Jun 9 at 8:46

You could do something like this

if (current_user_can('administrator')) {
    $pages = get_posts([
        'post_type' => 'page', // get only pages
        'posts_per_page' => -1, // get all
        'post_status' => array_keys(get_post_statuses()), // all post statuses (publish, draft, private etc...)
        'post__not_in' => [8,18,15,16,17] // list of ids you want to exclude (pages not for deletion)

    foreach ($pages as $page) {
        wp_delete_post($page->ID); // delete page (moves to trash)

If you want something quick without working with wp-cli.

I use this sometimes when I need to delete something quickly and once.

You can put this code in your, header.php (will probably get flamed for this XD), and enter your site, this code will only execute for administrator level users.

It will retrieve all pages you want to delete and delete them.

In post__not_in => [pages_ids_here] put all the pages ids you DO NOT want to delete.

wp_delete_post($page->ID) will do a soft delete, move it to trash, if you want to delete the pages permanently the use this wp_delete_post($page->ID, true) (not recommended straight away because you will not have a way to restore them, unless you did a DB backup).

Before you run this code, check what $pages contains to see if you got the correct pages, once you are sure that those are the correct pages you can delete them.

If you can do a DB backup in case something went wrong.

After all pages were deleted remove this code immediately to prevent unwated pages deletion in the future.

  • With 20k pages this might get you an "out of memory" error. if you want to go this way you probably need to break it down to chunks and might even need to use cron to delete the chunks – Mark Kaplun Jun 9 at 8:30
  • ... at the very least you want to get only the post ids from get_posts and not the full post data. Even then your DB might time out, but this is harder to call. – Mark Kaplun Jun 9 at 8:35
  • ... and sending 20k delete requests under one http request by itself might end up being a problem and get you into php execution timeout – Mark Kaplun Jun 9 at 8:37
  • @Buttered_Toast, thanks a lot for posting the answer but i need to verify things first as Mark Kaplun said. – shireef khatab Jun 9 at 8:43
  • @@Mark Kaplun, thanks a lot, do you know a better way, please? even with wp-cli, i can use that too. – shireef khatab Jun 9 at 8:43

I found it easier to first empty trash, then trash the pages I want to keep, then via wp-cli I delete all pages permanently (skip the trash with --force flag)


then restore the few trashed pages. hope that helps someone else.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.