How To Duplicate Posts In WordPress

There are many instances in which duplicating posts within WordPress might be useful. This article will outline a few of those examples and provide a few methods for duplicating posts.

Duplicate posts with a WordPress plugin

The easiest way to duplicate a post in WordPress is to use a plugin designed to do exactly that. Here are a few of our favorite plugins we use to duplicate posts in WordPress

Post Duplicator

The Post Duplicator is a lightweight post and page duplication plugin. It’s super easy to use and you can even change some basic configurations in its menu. It follows the WordPress admin setting guidelines. It can also duplicate custom post types if you have any of those created.

Duplicate Page and Post

Duplicate Page and Post is another easy-to-use plugin that allows you to duplicate posts and pages. Very simple to use. Simply head on to your posts and press the “Duplicate” button that is revealed when you hover your mouse over the posts you wish to duplicate.

Yoast Duplicate Post

Yoast Duplicate Post plugin allows users to clone posts of any type, or copy them to new drafts for further editing. It’s an easy-to-use plugin that offers a variety of ways to duplicate your posts from the posts menu and from the post itself.

How to duplicate posts in WordPress via the functions.php

If you don’t like plugins and wish to create the duplicate posts functionality yourself here’s how to. Simply copy the code from below and add it to your functions.php file. This will create a “Duplicate” button to your posts in the posts menu and will copy the post (including all meta fields) to a new post. This post will be a perfect copy of the original post you have created earlier, though will be in “Draft” mode.

 * @snippet  Duplicate posts and pages without plugins

// Add the duplicate link to action list for post_row_actions
// for "post" and custom post types
add_filter( 'post_row_actions', 'rd_duplicate_post_link', 10, 2 );
// for "page" post type
add_filter( 'page_row_actions', 'rd_duplicate_post_link', 10, 2 );

function rd_duplicate_post_link( $actions, $post ) {

	if( ! current_user_can( 'edit_posts' ) ) {
		return $actions;

	$url = wp_nonce_url(
				'action' => 'rd_duplicate_post_as_draft',
				'post' => $post->ID,

	$actions[ 'duplicate' ] = '<a href="' . $url . '" title="Duplicate this item" rel="permalink">Duplicate</a>';

	return $actions;

 * Function creates post duplicate as a draft and redirects then to the edit post screen
add_action( 'admin_action_rd_duplicate_post_as_draft', 'rd_duplicate_post_as_draft' );

function rd_duplicate_post_as_draft(){

	// check if post ID has been provided and action
	if ( empty( $_GET[ 'post' ] ) ) {
		wp_die( 'No post to duplicate has been provided!' );

	// Nonce verification
	if ( ! isset( $_GET[ 'duplicate_nonce' ] ) || ! wp_verify_nonce( $_GET[ 'duplicate_nonce' ], basename( __FILE__ ) ) ) {

	// Get the original post id
	$post_id = absint( $_GET[ 'post' ] );

	// And all the original post data then
	$post = get_post( $post_id );

	 * if you don't want current user to be the new post author,
	 * then change next couple of lines to this: $new_post_author = $post->post_author;
	$current_user = wp_get_current_user();
	$new_post_author = $current_user->ID;

	// if post data exists, create the post duplicate
	if ( $post ) {

		// new post data array
		$args = array(
			'comment_status' => $post->comment_status,
			'ping_status'    => $post->ping_status,
			'post_author'    => $new_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 post by wp_insert_post() function
		$new_post_id = wp_insert_post( $args );

		 * get all current post terms ad set them to the new post draft
		$taxonomies = get_object_taxonomies( get_post_type( $post ) ); // returns array of taxonomy names for post type, ex array("category", "post_tag");
		if( $taxonomies ) {
			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 );

		// duplicate all post meta
		$post_meta = get_post_meta( $post_id );
		if( $post_meta ) {

			foreach ( $post_meta as $meta_key => $meta_values ) {

				if( '_wp_old_slug' == $meta_key ) { // do nothing for this meta key

				foreach ( $meta_values as $meta_value ) {
					add_post_meta( $new_post_id, $meta_key, $meta_value );

* Redirect user to posts page in admin.
					'post_type' => ( 'post' !== get_post_type( $post ) ? get_post_type( $post ) : false ),
					'saved' => 'post_duplication_created' // just a custom slug here
				admin_url( 'edit.php' )

	} else {
		wp_die( 'Post creation failed, could not find original post.' );


 * In case we decided to add admin notices
add_action( 'admin_notices', 'rudr_duplication_admin_notice' );

function rudr_duplication_admin_notice() {

	// Get the current screen
	$screen = get_current_screen();

	if ( 'edit' !== $screen->base ) {

    //Checks if settings updated
    if ( isset( $_GET[ 'saved' ] ) && 'post_duplication_created' == $_GET[ 'saved' ] ) {

		 echo '<div class="notice notice-success is-dismissible"><p>Post copy created.</p></div>';

Duplicating posts from one WordPress to another

In some cases, you may find it necessary to duplicate posts from one site to another. WordPress has a built-in tool for this which you can use from the “Tools” menu. Simply head on to “Tools” and use the “Export / Import” functions to download an XML file of your posts that you can then import to your other site. A very handy tool for those who want to move or duplicate posts or pages from one WordPress to another.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *