Sometimes you’ll come across a situation when you want to create a new post or page that’s identical to (or nearly identical) to an existing post or page in your site.

If the post or page is long or includes a lot of media, the process of adding all that content all over again can seem very laborious. Also, if you have lots of posts that will be very similar one another, it’ll be very frustrating to have to either manually type out all of your text again or add all of the media files to create your new posts or pages.

One option might be to open up the existing post (for convenience, we’re going to use “post” to refer to posts and pages here) in one browser window or tab, then create your new post in another window and switch between the two of them, copying and pasting your content. After all, recent (post-Gutenberg) versions of WordPress do make this quite easy, with a “Copy all content” option available to you.

But if you have to do this again and again, there’s a risk of making errors. What if you accidentally edit the original post, overriding the content you already published to your site? Or if you have a large number of posts to copy and you lose track of which ones you’ve created?

It can be a potential headache.

Luckily there is an easier way. There are free plugins available that will let you make duplicates of your posts and pages, so you can edit and tweak them to create new posts that are almost identical to your existing content.


In this post, we’re going to show you some of the methods you can use to do this, and highlight some of the best plugins for the task.

But first, we’ll show you how to do duplicate a page or post in WordPress the semi-manual way, without a plugin. This involves copying and pasting but WordPress makes it so easy to do that, if you only have one post to copy, it’s probably going to be quicker than installing a plugin and doing it that way.

How to Duplicate a Page or Post in WordPress, the Semi-Manual Way

This method can be quicker if you just have one post to duplicate, as it saves you time installing a plugin. If you have a bunch of posts to duplicate, I’d seriously recommend skipping this section, though: you will find it much quicker, not to mention more accurate, to use a plugin.

So for those of you who just need to duplicate one post or page, here’s how to do it.

Start by opening your existing post or page. Make sure you don’t have an individual block selected by clicking outside a block on your post or selecting the Document tab in the editing pane to the right of the screen. If you have a block selected, WordPress will just copy the contents of that block and not the entire document.

Now click on the ellipsis at the top right of the editing screen (three dots arranged on top of each other).

The copy all content option in WordPress
The copy all content option in WordPress

A menu will appear. Towards the bottom of this menu, you’ll see a Copy All Content option. Click on it and you’ll get a message telling you your content has been copied.

Now create your new post. Give your post a title then click in the first empty block that’s been created for you on the editing screen. Use the shortcut keys for pasting on your keyboard (Ctrl + V on a PC, Cmd + V on a Mac, or right-click and select Paste in the shortcut menu that appears.

The contents of your older post will now appear in your new post. Magic! (OK, maybe not.)

Now you can edit that post and make it different from the older post. This is something I strongly advise doing – there isn’t much point in having blog posts that are exact duplicates of each other on your site. Not only will it confuse visitors, but it’s also bad for SEO.

But what if you want to create multiple duplicates of your post? Read on…

How to Duplicate a Page or Post in WordPress using a Plugin

By far the quickest, easiest and most reliable way to duplicate posts is by using a plugin. This will save you time, avoid any human error, and allow you to copy any post type you’d like. In fact, in our experience duplicating posts is actually more common with custom post types. It’s unusual to have two blog posts that are almost identical to each other, but it is quite common for products in a store, for example.

So here are some plugins that will make the process of duplicating posts easy, and guidance on how to use them.

WooCommerce

You may be wondering why I’ve included WooCommerce here, as it’s an ecommerce plugin, not a post duplication plugin.

But it’s worth knowing that WooCommerce lets you duplicate products without installing an extra plugin. So before you start searching for a post duplication plugin and using that to duplicate your products, just use the features that come bundled with WooCommerce.

If you go to the main Products screen in WooCommerce and hover your mouse over any product, you’ll see a Duplicate link under that post.

The WooCommerce duplicate product option
The WooCommerce duplicate product option

Simply click on that Duplicate link and a new product will be created. You’ll be taken straight to the editing screen for the new product so you can make changes to it and then publish it.

It’s worth noting that the slug for the new product will be the slug for the old product with -copy added, so even if you change the title of the new product, you’ll also need to edit the slug.

Editing a duplicated product
Editing a duplicated product

Duplicate Post Plugin

Duplicate Post is the most popular plugin for duplicating posts, with over 3 million downloads.

Once you’ve activated it, it adds a Clone link to each post in the main Posts screen in the WordPress admin.

the Duplicate Posts plugin
The Duplicate Post plugin

Click the Clone link under the post you want to duplicate, and a new post will be created for you with the same content and title and a Draft status.

You can then edit that new post and give it a new title (something I’d strongly advise – WordPress does let you duplicate titles but it isn’t very good for user experience).

It also adds the same Clone link to pages and for custom post types (if you enable them in the settings).

Duplicate Page

The Duplicate Page plugin has had over 900,000 downloads and is an alternative to the Duplicate Post plugin above.

Once you’ve installed the plugin, go to the Posts or Pages admin screen, or to the admin screen for your custom post type, and you’ll find a Duplicate This link under each post. Here’s mine with a custom post type:

The Duplicate Page plugin
The Duplicate Page plugin

Click on the link and you’ll get a new post (or page, or post of your custom post type) with the same content and title as the original post, with a status of Draft. You’ll need to edit it and amend its slug before publishing it.

Note: If you’re using WooCommerce, the Duplicate This link from this plugin won’t be displayed on your Products screen. WooCommerce overrides it with its own Duplicate link which I described earlier in this post.

How to Duplicate Posts or Pages in Bulk

The plugins I’ve already mentioned will let you duplicate posts one at a time. But what if you need to duplicate all the posts in your site, or all the posts of a custom post types? Or maybe all the posts you published this year?

The WP Bulk Post Duplicator plugin will let you do just that. Instead of adding a link to duplicate individual posts, it gives you a settings screen that lets you duplicate posts in bulk according to criteria you set.

Note: This plugin hasn’t been updated for two years at the time of writing, so we advise installing it on a development site and testing it before using it on a live site. We used it on our testing site with no problems.

Once you’ve installed the plugin, go to Settings > WP Bulk Post Duplicator to see the settings screen for the plugin.

Start by selecting the post types you want to duplicate as well as the post statuses. So if you select post and published, the plugin will duplicate all your published posts. If instead you select posts and draft, it will just duplicate all your draft posts.

Bulk Duplicate Settings - post type and status
Bulk Duplicate Settings – post type and status

Scroll down and select the year of the posts you want to duplicate (this is optional). You can also then specify the status of the new posts created. If you select nothing here, it will default to Draft.

Bulk Duplicate Settings - year and publish status
Bulk Duplicate Settings – year and publish status

Click the Duplicate button and the plugin will duplicate your posts. Here you can see all my pages duplicated, with 12 existing published pages, and 12 new draft pages. I then need to work through all the pages and edit them before publishing them. That will obviously take time, but it’s been made quicker by the bulk duplication,

Write Your Own Post Duplication Plugin

What if you don’t want to use a third party plugin to duplicate posts and you’d rather code your own?

No problem. Just follow these steps to create your own post duplication plugin.

1. Setting Up The Plugin

Start by setting up the plugin. Add a new file to your wp-content/plugins folder and add this commented out text to it (you can edit yours to reflect your author name):

<?php
/*
Plugin Name: Kinsta Duplicate posts and pages
Plugin URI: https://kinsta.com
Description: Plugin to accompany kinsta posst on duplicating posts in WordPress. Allows for duplication of posts and pages.
Version: 1.0
Author: Rachel McCollin
Author URI: https://rachelmccollin.com
TextDomain: kinsta
License: GPLv2
*/

2. Creating the Function

Now add the function for duplicating posts and hook it to an action hook. This action hook doesn’t exist yet: don’t worry, we’ll be creating it shortly.

function kinsta_duplicate_post(){
}
add_action( 'admin_action_kinsta_duplicate_post', 'kinsta_duplicate_post' );

Now let’s create that action, which will come as part of a function to add the duplication link to the posts and pages screens.

function kinsta_duplicate_post_link( $actions, $post ) {
 if ( current_user_can( 'edit_posts') ) {
  $actions['duplicate'] = 'Duplicate';
 }
 return $actions;
}
add_filter( 'post_row_actions', 'kinsta_duplicate_post_link', 10, 2 );
add_filter( 'page_row_actions', 'kinsta_duplicate_post_link', 10, 2);

That will add the link for duplicating, but it won’t actually duplicate anything yet.

3. Adding Duplication Functionality

Let’s add the code for the duplication. All of the rest of the code goes inside your empty kinsta_duplicate_post() function.

First, let’s check that a valid post has been selected and check for a nonce, for security:

global $wpdb;

// Die if post not selected
if (! ( isset( $_GET['post']) || isset( $_POST['post'])  || ( isset($_REQUEST['action']) && 'kinsta_duplicate_post' == $_REQUEST['action'] ) ) ) {
 wp_die( __( 'Please select a post to duplicate.', 'kinsta' ) );
}

// Verify nonce
if ( ! isset( $_GET['duplicate_nonce'] ) || ! wp_verify_nonce( $_GET['duplicate_nonce'], basename( __FILE__ ) ) ) {
 return;
}

Now we need to fetch the ID of the post to be duplicated, along with its data:

// Get id of post to be duplicated and data from it
$post_id = ( isset( $_GET['post']) ? absint( $_GET['post'] ) : absint( $_POST['post'] ) );
$post = get_post( $post_id );

We can use that to define an array of arguments and insert a new post into the database, using wp_insert_post(), But first, add a conditional statement to check that the post isn’t null:

if ( isset( $post ) && $post != null ) {

}

Add this inside that conditional statement:

// args for new post
$args = array(
 'comment_status' => $post->comment_status,
 'ping_status'    => $post->ping_status,
 'post_author'    => $post->post_author,
 'post_content'   => $post->post_content,
 'post_excerpt'   => $post->post_excerpt,
 'post_name'      => $post->post_name,
 'post_parent'    => $post->post_parent,
 'post_password'  => $post->post_password,
 'post_status'    => 'draft',
 'post_title'     => $post->post_title,
 'post_type'      => $post->post_type,
 'to_ping'        => $post->to_ping,
 'menu_order'     => $post->menu_order
);

// insert the new post
$new_post_id = wp_insert_post( $args );

Now we’ll fetch the taxonomies from the old post and add them to the new one:

// add taxonomy terms to the new post

// identify taxonomies that apply to the post type
$taxonomies = get_object_taxonomies( $post->post_type );

// add the taxonomy terms to the new post
foreach ( $taxonomies as $taxonomy ) {
 $post_terms = wp_get_object_terms( $post_id, $taxonomy, array( 'fields' => 'slugs' ) );
 wp_set_object_terms( $new_post_id, $post_terms, $taxonomy, false );
}

And then we’ll add any extra post metadata, using an SQL query:

// use SQL queries to duplicate postmeta
$post_metas = $wpdb->get_results("SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id=$post_id");
if ( count( $post_metas )!=0 ) {
 
$sql_query = "INSERT INTO $wpdb->postmeta ( post_id, meta_key, meta_value ) ";
 
foreach ( $post_metas as $post_meta ) {
  $meta_key = $post_metas->meta_key;
  if( $meta_key == '_wp_old_slug' ) continue;
  $meta_value = addslashes( $post_metas->meta_value);
  $sql_query_sel[]= "SELECT $new_post_id, '$meta_key', '$meta_value'";
 }

 $sql_query.= implode(" UNION ALL ", $sql_query_sel);
 $wpdb->query( $sql_query );

}

Finally, we check what post type the post is and redirect to the relevant screen.

// redirect to admin screen depending on post type
$posttype = get_post_type( $post_id );
wp_redirect( admin_url( 'edit.php?post_type=' . $posttype ) );

Now, outside the braces for the if ( isset( $post ) && $post != null ) check, we add an error message:

else {
 // display an error message if the post id of the post to be duplicated can't be found
 wp_die( __( 'Post cannot be found. Please select a post to duplicate.', 'kinsta' ) );
}

And that’s it!

The Full Plugin

Here’s the full code for the plugin:

<?php

/* Plugin Name: Kinsta Duplicate posts and pages

Plugin URI: https://kinsta.com
Description: Plugin to accompany kinsta posst on duplicating posts in WordPress. Allows for duplication of posts and pages. Version: 1.0 Author: Rachel McCollin
Author URI: https://rachelmccollin.com
TextDomain: kinsta
License: GPLv2
*/

/********************************************************************
kinsta_duplicate_post() - duplicates the selected post
*********************************************************************/

function kinsta_duplicate_post(){

global $wpdb;

// Die if post not selected
if (! ( isset( $_GET['post']) || isset( $_POST['post'])  || ( isset($_REQUEST['action']) && 'kinsta_duplicate_post' == $_REQUEST['action'] ) ) ) {

wp_die( __( 'Please select a post to duplicate.', 'kinsta' ) );
}

// Verify nonce
if ( ! isset( $_GET['duplicate_nonce'] ) || ! wp_verify_nonce( $_GET['duplicate_nonce'], basename( __FILE__ ) ) ) {
return;
}

// Get id of post to be duplicated and data from it
$post_id = ( isset( $_GET['post']) ? absint( $_GET['post'] ) : absint( $_POST['post'] ) );
$post = get_post( $post_id );

// duplicate the post
if ( isset( $post ) && $post != null ) {

// args for new post
$args = array(
'comment_status' => $post->comment_status,
'ping_status'    => $post->ping_status,
'post_author'    => $post->post_author,
'post_content'   => $post->post_content,
'post_excerpt'   => $post->post_excerpt,
'post_name'      => $post->post_name,
'post_parent'    => $post->post_parent,
'post_password'  => $post->post_password,
'post_status'    => 'draft',
'post_title'     => $post->post_title,
'post_type'      => $post->post_type,
'to_ping'        => $post->to_ping,
'menu_order'     => $post->menu_order
);

// insert the new post
$new_post_id = wp_insert_post( $args );

// add taxonomy terms to the new post

// identify taxonomies that apply to the post type
$taxonomies = get_object_taxonomies( $post->post_type );

// add the taxonomy terms to the new post
foreach ( $taxonomies as $taxonomy ) {

 $post_terms = wp_get_object_terms( $post_id, $taxonomy, array( 'fields' => 'slugs' ) );
 wp_set_object_terms( $new_post_id, $post_terms, $taxonomy, false );

}

// use SQL queries to duplicate postmeta
$post_metas = $wpdb->get_results("SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id=$post_id");

if ( count( $post_metas )!=0 ) {
 
 $sql_query = "INSERT INTO $wpdb->postmeta ( post_id, meta_key, meta_value ) ";

 foreach ( $post_metas as $post_meta ) {

  $meta_key = $post_metas->meta_key;
  if( $meta_key == '_wp_old_slug' ) continue;
  $meta_value = addslashes( $post_metas->meta_value);
  $sql_query_sel[]= "SELECT $new_post_id, '$meta_key', '$meta_value'";

  }

  $sql_query.= implode(" UNION ALL ", $sql_query_sel);
  $wpdb->query( $sql_query );

 }

 // redirect to admin screen depending on post type
 $posttype = get_post_type( $post_id );
 wp_redirect( admin_url( 'edit.php?post_type=' . $posttype ) );

 } else {

  // display an error message if the post id of the post to be duplicated can't be found
  wp_die( __( 'Post cannot be found. Please select a post to duplicate.', 'kinsta' ) );
 }

}
add_action( 'admin_action_kinsta_duplicate_post', 'kinsta_duplicate_post' );

// Add the duplicate link to action list for post_row_actions
function kinsta_duplicate_post_link( $actions, $post ) {

 if ( current_user_can( 'edit_posts') ) {
  $actions['duplicate'] = 'Duplicate';
 }

 return $actions;

}
add_filter( 'post_row_actions', 'kinsta_duplicate_post_link', 10, 2 );
add_filter( 'page_row_actions', 'kinsta_duplicate_post_link', 10, 2);

You can also find the full plugin on github.

Congratulations! You now have your own plugin to duplicate posts and pages in your WordPress site.

Credit: This code was partly written with reference to a post on the Hostinger blog.

Summary

Using a plugin to duplicate posts and pages can be quicker than doing it manually and can remove the risk of errors when copying content across.

If you only have one post to copy, you might find it quicker to use the inbuilt “Copy All Content” feature in WordPress, but for more than one post, it pays to use a plugin. If you use one of the plugins listed above, or maybe code your own, you’ll be able to duplicate as many posts, pages or custom post types as often as you want.

If you do it this way, you’ll save time and (more importantly), you’ll remove the risk of accidentally editing your original post when you should have edited the duplicate post.