9 min read

Fix Image Import Connection Timed Out Errors in WordPress

Shashank Dubey
Content & Marketing, Wbcom Designs · Published Aug 5, 2024 · Updated Aug 29, 2026
Connection Timed Out in WordPress

When you move a blog from one WordPress install to another, the built-in importer usually handles posts and pages fine and then stumbles on the media. You get a wall of “Failed to import Media” lines, or a blank screen after a minute, and the new site ends up with posts full of broken image links. The short answer is that the importer downloads every attachment over HTTP one file at a time inside a single PHP request, so any slow connection, short timeout or blocked request kills the run. Below is how we diagnose it and the order in which we apply fixes, from the quick ones to the ones that always work.

What the importer is actually doing

Three timeouts behind WordPress image import errors: PHP execution time, web server or CDN limits and the per-file fetch

The WordPress Importer plugin (version 0.9.x at the time of writing, maintained by the core team on WordPress.org) reads the WXR file you uploaded, creates the posts, and then, if you ticked Download and import file attachments, loops over every attachment entry in the file. For each one it calls wp_safe_remote_get() against the old site’s URL, streams the file to a temp location, hands it to the media library, regenerates thumbnails, and moves on to the next.

That whole loop happens inside the same web request that started when you clicked Submit. So three separate clocks are running against you:

  • The PHP max_execution_time on the new server (often 30 or 60 seconds on shared hosting).
  • The HTTP timeout in front of PHP. Nginx, Apache, LiteSpeed, Cloudflare and most managed hosts cut a request at 60 to 100 seconds regardless of what PHP allows.
  • The per-file timeout on the remote fetch. The importer sets this to 300 seconds, but the old server has to respond within that window for every single file.

“Connection timed out” in the import log means one of those clocks ran out while fetching a file. Which one tells you where to fix it.

Read the error before changing anything

Table decoding image import errors in WordPress, from cURL error 28 and 403 responses to zero size files and 524 timeouts

The importer prints a line per failed attachment. The text after the filename matters:

MessageMost likely causeWhere to look
Remote server did not respond / cURL error 28Old host is slow or rate-limiting, or a firewall blocks server-to-server requestsOld site’s hosting, WAF rules
Remote server returned error response 403 or 429Hotlink protection, Cloudflare bot rules, or a security plugin on the old siteOld site’s .htaccess, Cloudflare, Wordfence
Remote server returned error response 404File was already deleted, or the WXR has a URL from before a domain changeFix URLs in the WXR, or skip
Remote file is too large, limit is Ximport_attachment_size_limit filter or a host settingNew site’s PHP or a custom filter
Zero size file downloadedOld server returned an HTML error page instead of the imageOld site’s PHP errors or login redirect
Blank page, no log, 504 or 524Web server or CDN cut the request before PHP finishedNew site’s web server / Cloudflare

If you see a blank page or a 504 after roughly a minute, the failure is not PHP. Raising max_execution_time will not help because Nginx or Cloudflare has already closed the connection. Go straight to the WP-CLI section.

Quick fixes that sometimes work

1. Raise PHP limits on the destination

On shared hosting you can usually add these to the site root .htaccess (Apache or LiteSpeed) or a .user.ini file:

php_value max_execution_time 300
php_value max_input_time 300
php_value memory_limit 512M
php_value upload_max_filesize 64M
php_value post_max_size 64M

On Nginx plus PHP-FPM these go in the pool config or php.ini, and you also need fastcgi_read_timeout 300; in the server block or the web server will still drop the request at 60 seconds. Managed hosts (Kinsta, WP Engine, Cloudways) expose some of these in their dashboard and lock the rest. Kinsta, for example, documents a 300 second PHP limit and a 60 second HTTP limit, which is exactly the gap that bites imports. Their import troubleshooting guide recommends WP-CLI for the same reason we do.

2. Split the export file

A WXR file of a few hundred posts with 2,000 attachments will never finish in one browser request. Export by post type or by date range (Tools → Export → Posts, then pick a date range under the author and category filters) so each file carries a few dozen attachments. Import the files one after another. The importer keeps a map of already-imported attachments by original URL, so re-running a partially failed file mostly skips what it already has, though it will create duplicate posts if you imported those in a previous run. Delete the half-imported posts first or import posts and media in separate passes.

3. Check the old site is reachable from the new server

Your browser can see the old images; the new server might not. From SSH on the new host run:

curl -I https://old-site.com/wp-content/uploads/2024/05/photo.jpg

A 403 or a Cloudflare challenge page means the old site is blocking server requests. Common culprits are hotlink protection in cPanel, Cloudflare’s Bot Fight Mode, and “block fake Googlebots” rules in Wordfence or iThemes. Turn them off on the old site for the duration of the import, or allowlist the new server’s IP. If the old site is on a local dev box or behind basic auth, the new server cannot reach it at all, and you need the method below.

4. Make sure the old site does not redirect

If the old site forces HTTPS and the WXR contains http:// URLs, each fetch costs a redirect. That is fine on its own, but some hosts return the redirect as a 301 to a login page or a maintenance page, which the importer saves as a zero byte file. Open the WXR in a text editor and search and replace the scheme and domain if it has changed.

The reliable fix: run the import from WP-CLI

Fixing image import errors with WP-CLI in four steps: install the importer, upload the WXR, run wp import, debug in tmux

Running the importer from the command line removes the HTTP timeout entirely and usually removes the PHP one too, because CLI PHP defaults to an unlimited max_execution_time. It is the only method we use for anything over a few hundred posts.

  1. Install and activate the WordPress Importer plugin on the new site (it provides the command).
  2. Upload the WXR file(s) to the server, outside the web root if you can, for example ~/imports/.
  3. From the WordPress root run:
wp import ~/imports/blog-export.xml --authors=create

The --authors flag accepts create (make missing users), skip, or a path to a CSV for mapping old authors to existing users. Attachments are fetched by default. If you want to import content first and deal with media separately, add --skip=attachment; if thumbnails are what is slow, --skip=image_resize imports the originals and lets you regenerate sizes later with wp media regenerate.

Two more things make CLI imports smoother. Add define( 'IMPORT_DEBUG', true ); to the wp-config file temporarily so every fetch failure prints its reason instead of a generic line. And run the command inside screen or tmux so a dropped SSH session does not kill a two hour import. The full option list is in the WP-CLI import reference.

On hosts without SSH (many shared plans), ask support to run the command for you, or do the import on a local copy and move the finished site up with a migration plugin. Both beat fighting the browser importer for an afternoon.

Copy the uploads folder and skip remote fetching altogether

Fetching 5 GB of images one at a time over HTTP is the slow part. Copying the folder is fast. If you have file access to both sites:

  1. Copy wp-content/uploads from old to new with rsync, SFTP, or a zip through the hosting file manager. With rsync: rsync -avz user@old-host:/path/to/wp-content/uploads/ ./wp-content/uploads/
  2. Run the import with attachments disabled: wp import file.xml --authors=create --skip=attachment, or untick the attachments box in the browser importer.
  3. Rewrite the old domain to the new one in content: wp search-replace 'old-site.com' 'new-site.com' --skip-columns=guid
  4. If the attachment posts themselves matter to you (for galleries, featured images, or the media library listing), register the copied files with a plugin such as Media Sync or run wp media import wp-content/uploads/2024/*/*.jpg --skip-copy for the folders you need.

Featured images are the catch here. The importer maps _thumbnail_id from old attachment IDs to new ones only when it imports the attachment. If you skip attachments, posts keep the old IDs and the featured image box shows nothing. For a full move (rather than merging a blog into an existing site), the better route is a full-site migration with the database included, which sidesteps the importer completely. We covered the tooling in our backup and migration plugin comparison, and our migration service does exactly this when clients have large libraries.

Filters worth knowing if you are a developer

The importer exposes a few hooks that help with edge cases. Put these in a small mu-plugin, not the theme, so they are active during CLI runs too.

// Allow large files (default is unlimited, but some hosts filter this down).
add_filter( 'import_attachment_size_limit', function () {
    return 200 * 1024 * 1024; // 200 MB
} );

// Give each remote fetch more time and send a browser-like UA past picky firewalls.
add_filter( 'http_request_args', function ( $args, $url ) {
    if ( false !== strpos( $url, 'old-site.com' ) ) {
        $args['timeout']    = 600;
        $args['user-agent'] = 'Mozilla/5.0 (compatible; WP Importer)';
    }
    return $args;
}, 10, 2 );

// Skip attachment fetching entirely without touching the UI.
add_filter( 'import_allow_fetch_attachments', '__return_false' );

Another useful trick when the old domain has already gone dark but you have the files: serve the old uploads folder from a temporary subdomain on the new host, then rewrite the URLs inside the WXR file to that subdomain before importing. The importer fetches everything locally at full speed and the result is a clean media library with correct IDs.

A typical scenario

A client recently asked us to fold a 900-post photography blog into their BuddyX community site. The browser importer died at post 140 every time with a 524 from Cloudflare. PHP limits were fine (300 seconds); the problem was the 100 second edge timeout. We exported by year into six WXR files, rsynced 11 GB of uploads across, ran wp import --skip=attachment for each file in a tmux session, then re-imported only the attachment entries with a small script so featured images mapped correctly. Total time about 40 minutes, most of it the rsync. No timeouts, no duplicate posts.

FAQ

Does re-running a failed import create duplicates?

Posts yes, attachments mostly no. The importer checks for an existing post with the same title, type and date and skips it, but that check is easy to defeat (edited titles, different timezones). Clear out partial imports before retrying, or split by post type so each run is self-contained.

Why do images import but show as broken in posts?

The files came across, but the post content still references the old domain. Run wp search-replace for the old URL, or use the Better Search Replace plugin if you have no CLI. Check the image srcset attributes as well; those carry the old domain in every size variant.

Can I increase the timeout from the browser importer alone?

Only the PHP part, and only if your host lets you. The web server and CDN timeouts sit outside WordPress and cannot be changed from inside it. That is why CLI or a file copy is the dependable route.

Is All-in-One WP Migration or Duplicator a better choice?

For moving an entire site, yes. Those tools package the database and files together and restore them in chunks, so timeouts rarely matter. For merging one blog’s posts into an existing site while keeping that site’s users, settings and plugins, the WXR importer is still the right tool, which is why it is worth learning to run it properly.

Where to start

Look at the exact error text first. A 403 means fix the old site’s firewall. A 504, 524 or blank screen means stop using the browser and switch to WP-CLI. A huge library means copy the uploads folder and import with --skip=attachment. Work through those three in order and the “connection timed out” problem goes away for good.

Shashank Dubey
Content & Marketing, Wbcom Designs

Shashank Dubey, a contributor of Wbcom Designs is a blogger and a digital marketer. He writes articles associated with different niches such as WordPress, SEO, Marketing, CMS, Web Design, and Development, and many more.

Related reading