When you start seriously tinkering with a website — in WordPress or any other system — you need to internalize one basic rule before you begin: don’t experiment in production.
For several reasons:
- Because the results can be catastrophic if you don’t really know what you’re touching or you don’t have a backup.
- Because, as a result, while you restore everything, you can suffer a very unpleasant spike of stress.
- And because setting up a local copy will take you only half an hour, and you will be eternally grateful for it.
I’ll repeat it:
First you set up a local copy. Then you touch things. Not the other way round.
These days I’ve been changing my website quite thoroughly, so I had to do it, and I took the opportunity to create this tutorial.
My site had several years of content, 250 posts, images accumulated since 2013, and enough size for Duplicator to stall halfway twice before finally working.
That is here too. The failures — and their fixes — included.
Índice de Contenidos del Artículo
- What a local WordPress clone is useful for
- Tools I used
- Step-by-step guide to cloning your WordPress locally
- Step 1: install LocalWP
- Step 2: check that the local WordPress opens
- Step 3: install Duplicator on the real website
- Step 4: create a copy with Duplicator
- Step 5: try DupArchive if ZIP fails
- Step 6: create the package without the uploads folder
- Step 7: download the Duplicator files
- Step 8: download the uploads
- Step 9: prepare LocalWP to import the copy
- Step 10: run the Duplicator installer locally
- Step 11: clean up the installation files
- Step 12: copy uploads into the local WordPress
- Step 13: fix the broken images problem
- Step 14: fix visible warnings
- Step 15: clean up production
- Step 16: test the local clone
- Step 17: create a restore point before continuing
- Common problems in this process
- Conclusion
- Frequently asked questions
- Can I clone WordPress locally for free?
- Why does Duplicator fail when creating the ZIP?
- Can I exclude uploads from the Duplicator package?
- Why are images not visible in local WordPress?
- Is it safe to install Duplicator in production?
- Do you have to activate cache plugins locally?
- Why create a clone before installing Polylang?
What a local WordPress clone is useful for
A local copy lets you work on your computer without touching the real website.
Useful for: testing plugins, changing themes, reviewing the database, preparing a migration, doing a technical audit, installing Polylang, modifying CSS or breaking things without Google, your users or your client noticing.
In my case, the goal was twofold:
- Completely change the design, moving from a lead-generation website to a digital magazine.
- Prepare the website for AI-assisted translation. A custom development with a certain level of risk, since it involves touching several things at once.
In any case, the process is the same if you want to recategorize automatically, change themes, add a large plugin like WooCommerce, or simply have a test environment before touching anything serious.
Tools I used
- LocalWP: to create the local WordPress environment.
- Duplicator: to export the production website.
- cPanel: the hosting control panel, used to manually download the images folder.
- WP-CLI: included in LocalWP, used to correct internal WordPress options.
All free.
Step-by-step guide to cloning your WordPress locally
Now that you know the tools, let’s go through the step-by-step process, which is a little longer than usual.
In any case, to give you an idea, in about 30 minutes you’ll have everything ready, depending on the problems that come up. Because if your site is small and throws no errors, you may have it done in under ten minutes.
Few investments pay off better than this one.
Step 1: install LocalWP
LocalWP creates local WordPress installations without having to configure Apache, MySQL and PHP by hand. You don’t need XAMPP, WAMP or LAMP.
You install it, create a new site and in two minutes you have a clean WordPress running on your computer.
In my case I called it yg, so LocalWP assigned it the local domain https://yg.local with this environment:
| Field | Value |
| Server | nginx |
| PHP | 8.2 |
| Database | MySQL |
| WordPress | Clean installation |
That is enough to get started.
Step 2: check that the local WordPress opens
Before importing anything, open the local site and enter the dashboard:
- https://yg.local
- https://yg.local/wp-admin
If it loads and you can log in, the environment is ready. Don’t install anything yet. Don’t touch settings. Just check that it works.
Step 3: install Duplicator on the real website
Go into the production WordPress site (not the local one) and install Duplicator:
Plugins > Add New > Duplicator
Install and activate it.
Important: Duplicator is installed in production. The idea is to generate a package of the real website and then import it into LocalWP.
Step 4: create a copy with Duplicator
From the production dashboard, go to:
Duplicator > Packages
Create a new package with a name that identifies what it is for. I used:
yagogonzalez-copia-local-fase0
The initial scan warned that the site was large. Nothing unusual on websites with years of content.
The problem came when building the package:
Couldn't close zip archive
The server could not close the ZIP archive.
It does not mean the website broke. It means the hosting could not complete the operation, probably because of size, execution time or memory limits.
First problem to solve.
Step 5: try DupArchive if ZIP fails
Duplicator offers an alternative when ZIP fails: DupArchive.
To do that, you need to change the archive engine from ZIP to DupArchive. The package is then generated as .daf instead of .zip.
You change it from:
Duplicator > Settings > Backups > Archive
There, look for Archive Engine and change ZipArchive to DupArchive.
Then save the changes.
All set?
Not quite. New error:
The total size of the files and database exceeds the 500 MB limit
The copy weighed approximately 1.33 GB. Changing everything just for the sake of it was no use either.
The solution: not to put everything inside the package.
Step 6: create the package without the uploads folder
The folder that makes any WordPress with years behind it balloon in size is wp-content/uploads/.
That is where images, PDFs, thumbnails, WebP files and everything uploaded since day one live.
To reduce the download package, I enabled file filters in Duplicator and excluded:
- wp-content/uploads/
- wp-content/cache/
- wp-content/upgrade/
- wp-content/backups-dup-lite/
- wp-content/plugins/duplicator/backups/
With this, the package includes what matters to rebuild the website: database, WordPress, theme, plugins, configuration, posts, pages, taxonomies, ACF, Yoast and internal settings.
We download the images separately. I’ll explain how in step 8.
Step 7: download the Duplicator files
Once the package is generated, Duplicator creates two files:
- installer.php
- .zip or .daf file
Download both.
They are what allow you to rebuild the website locally. The installer handles extracting the package, importing the database, replacing URLs and adjusting paths.
Step 8: download the uploads
Since uploads was not inside the package, you have to download it manually from the hosting.
The usual path in WordPress is:
/public_html/tudominio.com/wp-content/uploads/
If you have standard hosting, you can download it from the cPanel file manager. That is what I did.
If you cannot do it this way, you will have to do it the old-school way, downloading it via FTP or SFTP directly to your computer with FileZilla or similar.
Tip: don’t compress the folder on the server. That would put load back on the hosting and could fail just like Duplicator. Direct download is slower, but safer.
Step 9: prepare LocalWP to import the copy
With the two Duplicator files downloaded, go back to LocalWP:
- For the local site: click Stop site.
- Open the site folder: click Site folder.
- Go into app > public.
- Delete the contents of public (the clean WordPress that LocalWP created).
- Copy the two Duplicator files there.
Important: you have to delete the contents of public, not the public folder.
The folder must exist, and inside it there should only be the two downloaded files:
- installer.php
- copia-local.daf
Then start the site: click Start site.
Step 10: run the Duplicator installer locally
Open the installer in the browser:
https://yg.local/installer.php
The installer detects the package and starts the process.
To connect to the local database, use the LocalWP data:
| Field | Value |
| Database Host | localhost |
| Database Name | local |
| User | root |
| Password | root |
Since it was an empty local installation (the one the program sets up by default at the start), tell it that you accept that Duplicator deletes the previous database.
Nothing happens: it was only deleting LocalWP’s clean WordPress, not the real website.
Then Duplicator does the URL replacement:
- Old URL: https://yagogonzalez.com
- New URL: https://yg.local
When it finishes, you can now log into the local WordPress.
Important: after importing the database, the username and password are those of the real website, not the ones initially created in LocalWP.
Step 11: clean up the installation files
Duplicator normally deletes the installer files when it finishes:
- installer.php
- .daf file
- dup-installer folder
- installation logs
In production this is important for security. Locally it is less critical, but it is worth leaving everything clean.
Check that they do not exist after the installation before continuing.
Step 12: copy uploads into the local WordPress
With the site stopped (Stop site) in LocalWP, go into app > public > wp-content and copy there the uploads folder you downloaded.
The correct structure:
<em>wp-content/</em>
├── plugins/
├── themes/
└── uploads/
├── 2013/
├── 2014/
...
└── 2026/
What must not happen:
wp-content/uploads/uploads/2026/
That double uploads/uploads is a classic mistake from compressing in ZIP before downloading, and it breaks all the image paths.
Step 13: fix the broken images problem
In my case, this is where the biggest problem arrived (because it was unexpected): the site loaded, but the images did not show. And it was not because of the double upload path.
The problem was in the URL WordPress generated for the images:
https://yg.local/C:/Users/pcadmin/Local Sites/yg/app/public/wp-content/uploads/2026/06/imagen.webp
Everything marked in bold was extra. The correct URL had to be:
https://yg.local/wp-content/uploads/2026/06/imagen.webp
WordPress had stored in the upload_path option an absolute Windows path:
C:/Users/pcadmin/Local Sites/yg/app/public/wp-content/uploads
To fix it, open Site shell in LocalWP and run these three commands one after another:
wp --url=https://yg.local option delete upload_path
wp --url=https://yg.local option delete upload_url_path
wp --url=https://yg.local cache flush
Once done, after reloading, the images appeared.
The problem is that several Warnings (warnings) also appeared.
Step 14: fix visible warnings
As I said, this warning appeared on the local site:
Constant WP_POST_REVISIONS already defined
Here I turned to ChatGPT, because I had no idea how to fix it.
The problem came from the theme’s functions.php , which defined WP_POST_REVISIONS without checking whether it was already defined somewhere else.
The fix:
<em>if ( ! defined( 'WP_POST_REVISIONS' ) ) {</em>
<em> define( 'WP_POST_REVISIONS', false );</em>
<em>}</em>
If in your case the value is different, simply keep yours:
<em>if ( ! defined( 'WP_POST_REVISIONS' ) ) {</em>
<em> define( 'WP_POST_REVISIONS', <strong>5</strong> );</em>
<em>}</em>
I changed it from WordPress’s theme file editor (Appearance > Theme File Editor), saved the file and that was it.
Step 15: clean up production
With the local copy working, go back to the real website and remove Duplicator’s traces:
- Duplicator > Packages: delete the packages created.
- Plugins > Installed Plugins: uninstall Duplicator.
This does not affect the local copy. It only avoids leaving heavy packages and unnecessary installers in production.
It is not mandatory, but it is recommended.
Step 16: test the local clone
Check several URLs before continuing.
In my case I reviewed:
- The homepage.
- A post.
- A category.
- A subcategory.
- A tag.
I did it that way because each one uses a different template:
- https://yg.local
- https://yg.local/ruta-de-escape
- https://yg.local/tecnologia
- https://yg.local/ocio/series
- https://yg.local/negocio
Four things to check:
- The website loads.
- The images are visible.
- The design is the same as in production.
- Internal links point to yg.local, not to yagogonzalez.com.
This last point is key. If you click on an article and it sends you to production, you still have badly replaced URLs.
Step 17: create a restore point before continuing
This step is again optional, but recommended.
Before you start making the changes you need locally or touching anything serious, create a restore point.
In LocalWP you can clone the site:
Clone site
In my case I created a copy called yg-pre-polylang.
The logic:
- yg = working local site.
- yg-pre-polylang = clean copy before touching anything.
If something blows up, you do not have to repeat the whole migration from production from scratch; instead, I take this clean copy and work on it. Not before cloning it again, of course.
Common problems in this process
Local migrations almost never work perfectly the first time. I’m grouping here the ones that appeared in this case.
Duplicator ZIP failed
Error: Couldn't close zip archive
Cause: server limits (size, execution time, memory).
Solution: try DupArchive or exclude heavy folders from the package.
DupArchive had a size limit
Error: the package exceeded 500 MB.
Solution: exclude wp-content/uploads/ and download that folder separately.
Images did not load
Cause: WordPress was using an absolute Windows path as if it were a public URL.
Solution:
wp option delete upload_path
wp option delete upload_url_path
PHP warning because a constant was already defined
Cause: WP_POST_REVISIONS defined twice in functions.php.
Solution: wrap the definition with if ( ! defined(…) ).
Conclusion
If your website is small, Duplicator does everything by itself. But if it has years of content and accumulated images, the usual thing is to split the process in two:
- Duplicator = database + WordPress + theme + plugins
- FTP/SFTP = uploads folder
And then review paths, images, warnings and internal links before touching anything serious.
A local copy is worthless if it does not really work.
And if you are going to touch something delicate — multilingual setup, redesign, large plugins, SEO migrations — doing it directly in production is taking unnecessary risks.
You have the tools. They are free. And the process, even if it is not automatic, takes half an hour.
Remember:
First local. Then tests. Then production. In that order.
Like Bale and golf, but applied to WordPress.
By the way, here is the follow-up to this article: how to optimize WPLocal speed.
Frequently asked questions
Can I clone WordPress locally for free?
Yes. LocalWP, Duplicator and FTP/SFTP are free. If the website is large, you will have to do part of the process manually, such as downloading uploads separately, but you do not need to pay anything.
Why does Duplicator fail when creating the ZIP?
Because of server limits: maximum size, execution time or memory. The most direct solution is to switch to DupArchive or exclude heavy folders such as uploads before generating the package.
Can I exclude uploads from the Duplicator package?
Yes. You exclude it in Duplicator’s filters and download that folder separately via FTP or SFTP. Then you copy it manually intowp-content/uploads/inside the local site.
Why are images not visible in local WordPress?
It is almost always because theupload_pathoption is misconfigured. If in the image URL you see something likeC:/Users/..., that is the problem. It is fixed by deleting that option with WP-CLI.
Is it safe to install Duplicator in production?
Yes, but only for as long as necessary. Once the copy is downloaded, delete the packages and uninstall the plugin.
Do you have to activate cache plugins locally?
Not at first. First validate that the clone works: images, URLs and design. Then, if you want to replicate production behavior, activate WP Rocket or another cache plugin.
Why create a clone before installing Polylang?
Because Polylang touches URLs, taxonomies and relationships between content. If something breaks, you want to be able to roll back without repeating the entire migration.

Leave a Reply