Your posts imported fine. Your images did not.

The failed to import media error in WordPress appears during site migrations, XML imports, and one-click demo installs, and it always means the same thing: the WordPress Importer could not download a file and write it into wp-content/uploads.

Sometimes the old attachment URL returns a 404. Sometimes it’s PHP memory, folder permissions, or a firewall quietly refusing the request.

This guide covers:

  • What each error message actually tells you
  • A ten-minute diagnosis before you change any settings
  • Fixes for server limits, permissions, SSL, and blocked requests
  • Manual media transfers, stronger import tools, theme demos, and WooCommerce CSV uploads

What Is the Failed to Import Media Error in WordPress

“Failed to import media” is the WordPress Importer’s response when it cannot download a file listed in your export file and save it into wp-content/uploads. Post content usually lands fine. The attachment record and the physical image do not.

The error shows up under Tools > Import > WordPress, and the same failure pattern repeats in theme demo installers and migration plugins.

The official WordPress Importer plugin sits at 3M+ active installations on WordPress.org, which is a big part of why this one error message generates so many support tickets.

Worth saying early: a blank media library after a migration is a symptom, not a separate problem. Same root cause, different screen.

What the WordPress Importer Does With Media Files

The importer runs a 3-step sequence for every attachment in the file.

Have you seen the latest WordPress statistics?

Discover the latest WordPress statistics: market share, security trends, performance data, and revenue insights that shape the web.

Check Them Out →
  • Read: pulls the URL from the wp:attachmenturl tag inside the WXR file
  • Fetch: calls the remote file over HTTP with wpremoteget
  • Write: saves it to wp-content/uploads and registers a post of type attachment

The XML export file holds only the reference, never the file itself. WordPress.org documents this directly in the importer FAQ.

Two filters control the behaviour: importallowfetchattachments (returns false to skip media entirely) and importattachmentsizelimit (caps file size in bytes).

Which Error Messages Belong to This Failure Type

Same underlying failure, different wording depending on where it broke.

MessageWhat it actually means
Remote server did not respondThe source server was unreachable or the request timed out while fetching the file.
Remote server returned error response: 404 Not FoundThe attachment URL no longer exists or the file has been moved.
Remote file is incorrect sizeThe download was truncated, often because a challenge or error page was saved instead of the image.
Sorry, this file type is not permitted for security reasonsThe file’s MIME type is not on the allowed list (for example, SVG, AVIF, or WebP on older WordPress versions).

By default the importer prints the short version. Setting define(‘IMPORTDEBUG’, true); in wp-config.php turns each line into something you can act on.

What Causes Failed Media Imports in WordPress

Failed media imports have 3 root causes: an unreachable source file, a destination server that runs out of resources mid-job, or a network layer that blocks the request. Every fix in this guide belongs to one of those three buckets.

Match the symptom to the bucket before you start editing files. Nothing wastes an afternoon faster than raising memory limits on a problem that was a 404 the whole time.

Source Side Causes

The old site is the single most common culprit.

  • Source site already taken offline, expired, or pointed at new nameservers
  • Media deleted after the export was generated
  • Attachment URLs carrying query strings (?sc=12) that the source no longer honours
  • Export file generated months ago against a library that has since changed

Devowl’s teardown of this error makes the same point: if the old source is gone, the importer has nothing to download and throws the error every single time.

Destination Server Causes

Resource ceilings: WordPress defaults WPMEMORYLIMIT to 40M on single sites and 64M on multisite, hardcoded in wp-includes/default-constants.php.

Upload ceilings: PHP ships with uploadmaxfilesize at 2M and postmaxsize at 8M according to the PHP manual, which chokes on any decent image library.

Time ceilings: maxexecutiontime commonly sits at 30 seconds and maxinputtime at 60.

Permissions and disk quota round out the list. A directory that cannot be written to fails silently more often than it throws a readable warning, which is why media upload problems and import failures share so many fixes.

Network and Security Causes

Both servers can be perfectly healthy and the request still never completes.

Wordfence alone runs on 5M+ WordPress sites, and a firewall that treats server-to-server fetches as bot traffic will block them without telling you.

  • Hotlink protection rejecting requests with a foreign or empty referer
  • Cloudflare Bot Fight Mode returning a challenge page instead of the image
  • ModSecurity throwing 403 on bulk outbound requests from shared hosting
  • Basic auth on the source (default on WP Engine and Kinsta staging environments)

How to Diagnose the Exact Cause of a Failed Media Import

Copy one failing image URL out of the export file and open it in a browser. That single test splits the problem in half. A 404 means the cause is source side and no server tweak will help. A loading image means the problem lives on your end.

Everything below runs in about ten minutes.

The Test Sequence

Open the WXR file in VS Code or Sublime (not Word, it will mangle the encoding) and search for wp:attachmenturl.

Paste one URL into a private browser window. Private window matters, because a cached login on the source can make a protected file look public.

Then enable logging. Set WPDEBUG and WPDEBUGLOG to true, WPDEBUGDISPLAY to false, and read the log file at /wp-content/debug.log.

If nothing useful lands there, switching PHP error output on catches the failures WordPress swallows.

Server Side Checks

Confirm outbound requests work. SSH into the destination and run curl -I against the source image URL. A 200 proves the connection is allowed. A 403 or a timeout points straight at the firewall.

Read the real limits, not the assumed ones. Site Health > Info > Server reports live values for memorylimit, maxexecutiontime, and postmaxsize.

Watch the import happen. Keep the DevTools Network tab open during the run. A 500 response or a truncated request tells you the PHP process died rather than the fetch failing.

How to Raise the Server Limits That Stop Media Imports

Set memorylimit to 256M, maxexecutiontime to 300, uploadmaxfilesize and postmaxsize to 128M, and maxinputtime to 300. Those five values clear the large majority of import failures on shared and VPS hosting.

The WordPress Importer FAQ still references the classic symptom: “Fatal error: Allowed memory size of 8388608 bytes exhausted” while parsing a large export.

DirectiveRecommended valueFailure it fixes
memory_limit256MAllowed memory size exhausted
max_execution_time300Import stops before completion
post_max_size128MRequest Entity Too Large during upload
upload_max_filesize128MWXR file is rejected before parsing

Where to Set PHP Limits by Host Type

Shared and cPanel hosting

Use the MultiPHP INI Editor, or drop the directives into the php.ini file in your site root. On CloudLinux with CageFS a root php.ini gets ignored, so Select PHP Version > Options is the reliable path.

Managed WordPress hosting

WP Engine caps WordPress memory at 512MB and documents the wp-config.php constants under its own settings block. Kinsta and Pressable handle php.ini at the platform level, so a support ticket beats an FTP session.

Which Limit Maps to Which Error Message

One detail trips people up constantly. wp-config.php cannot raise uploadmaxfilesize, because it is a PHPINIPERDIR directive and PHP has already finished reading it by the time WordPress boots.

WPMEMORYLIMIT works differently. It requests memory rather than granting it, and it can never exceed the server’s memorylimit.

Raise postmaxsize and uploadmaxfilesize together, always. Raising one alone makes the upload fail silently before WordPress ever sees the file.

Verify with a phpinfo() file or Site Health. Assuming the edit worked is how people spend two hours fixing a limit that never changed.

How to Fix Upload Folder Permission and Ownership Errors

Set directories to 755 and files to 644, with ownership matching the PHP process user. The WordPress Advanced Administration Handbook states this baseline plainly and adds one hard rule: no directory should ever be given 777, upload folders included.

This failure mode is sneaky because it often produces no error text at all. The importer reports a media failure, the log stays quiet, and the uploads folder sits there unwritable.

Over SSH:

  • find /path/to/wp-content/uploads -type d -exec chmod 755 {} ;
  • find /path/to/wp-content/uploads -type f -exec chmod 644 {} ;
  • chown -R www-data:www-data wp-content/uploads (swap in your own web server user)

No SSH? FileZilla handles it through File Permissions with “Recurse into subdirectories” ticked, though you have to run directories and files as two separate passes.

chmod 777 will “fix” this in about four seconds. It also opens the folder to every account on a shared server, so treat it as a diagnostic test and revert immediately. Full context sits in the guide to correcting WordPress permissions.

When Permissions Are Not the Problem

Disk quota: a full account produces identical symptoms with zero permission errors. Check with df -h or your host’s storage meter.

Missing parent folders: uploads uses a year/month structure (2026/07). If the parent cannot be created, nothing inside it gets written either.

How to Fix Imports Blocked by Firewalls, Hotlink Protection, and Security Plugins

Deactivate the security plugin, allowlist the destination server IP on the source, and drop Cloudflare into Development Mode for the length of the import. Three moves that cover almost every blocked-request scenario.

The awkward part is that both sites report themselves as perfectly healthy while this happens.

BlockerSymptomFix
Wordfence, Sucuri, or Solid SecurityImport fails immediately with no log entryDeactivate the security plugin, run the import again, then reactivate it
Cloudflare Bot Fight ModeRemote file is incorrect sizeEnable Development Mode or temporarily pause Bot Fight Mode on the source site
Hotlink protection403 errors for every image while HTML imports successfullyAllowlist the destination server’s IP address
ModSecurityBulk image fetches return 403 ForbiddenAsk your hosting provider to whitelist the triggered ModSecurity rule ID

The challenge page detail deserves attention. Cloudflare returns an HTML interstitial with a 200 status, the importer saves it as the image, and you end up with a library of 4KB files that are technically valid and completely useless.

Staging environments cause the other half of these tickets. WP Engine and Kinsta password-protect staging by default, so an export generated there points at URLs your new server cannot open.

How to Fix Media Imports Broken by SSL, Redirects, and URL Mismatches

Open the WXR file, find and replace http:// with https:// across the attachment URLs, then re-import. With 87% of all websites now serving HTTPS by default (W3Techs, January 2026), a protocol mismatch inside an older export is a routine cause.

The importer follows some redirects and gives up on others. Chains are where it reliably stops.

Editing the WXR File Before Import

Search the export for the old domain inside wp:attachmenturl tags. That tells you exactly what the importer will request, which beats guessing.

Use a code editor. VS Code, Sublime, or Notepad++ handle multi-megabyte XML without re-encoding it. Word processors quietly convert straight quotes into curly ones and break the parse.

After the import, clean up whatever URLs did land using Better Search Replace or the WP-CLI command wp search-replace.

Direct database edits are the trap here. Serialized theme option data stores string lengths, so a manual URL swap corrupts the array and takes your customizer settings with it.

Fixing Certificate and Redirect Failures on the Source

wpremoteget verifies certificates by default. An expired, self-signed, or mismatched certificate on the old site kills the fetch before a single byte transfers.

Check first: load the source over https in a browser and look for a warning. A Let’s Encrypt certificate that lapsed after the site was decommissioned is the usual story, and certificate problems on WordPress follow the same diagnostic path here.

Then flatten the redirects. A non-www to www hop followed by an http to https hop is two redirects deep, and the importer regularly abandons the request there. Point the export at the final URL instead.

Get this wrong and the posts import with paths to a domain that no longer serves files, which is a slightly different flavour of images refusing to display than a failed fetch produces.

How to Import Media Manually When the WordPress Importer Keeps Failing

Copy the entire wp-content/uploads folder from the old site to the new one over FTP or SSH, then register the files as attachments. The importer never has to fetch anything remotely, so every network, firewall, and timeout cause disappears at once.

This is the fallback that works no matter which of the earlier causes you were fighting.

Transfer: FileZilla for smaller libraries, rsync or scp once you pass a couple of gigabytes.

Preserve structure: the year/month folders (2026/07) have to land exactly as they were, because every attachment path in the database points at them.

Register: Add From Server or Media Library Assistant scans the directory and creates the missing attachment records.

Skipping that third step is the classic mistake. The files sit on disk, the media library shows nothing, and the debug log fills with failed to open stream warnings pointing at paths that technically exist.

Finishing the Job

Regenerate the intermediate image sizes once the attachments exist. Kinsta’s guide makes the case for doing it through WP-CLI rather than a plugin, since the command line is not subject to HTTP limits or timeouts.

wp media regenerate –yes handles the whole library. Add –only-missing to skip images that already have their sizes.

Featured images need reconnecting separately, either with Auto Post Thumbnail or a manual pass on the posts that matter.

One practical note on big libraries: zipping 5GB of uploads usually fails on shared hosting. Split the transfer by year folder and it goes through fine.

Pulling the Files Off a Site You Can Still Access

If the old dashboard still loads, exporting the media library directly beats hunting through FTP folders.

Watch the upload side too. Manual uploads through the dashboard on the new site can throw HTTP error on upload, which is a memory or ImageMagick problem rather than an import problem.

Which Import Tools Handle Media Better Than the Default WordPress Importer

Tools that bundle the uploads folder inside the migration archive beat tools that fetch each file over HTTP. All-in-One WP Migration, Duplicator, and UpdraftPlus move media as part of the package. WP All Import and WP-CLI retry and chunk instead.

Pick based on which failure you are trying to avoid, not on which plugin has the nicest interface.

ToolMedia approachFree version limit
All-in-One WP MigrationIncludes uploads inside the backup archive512 MB import limit
DuplicatorCreates a package archive with an installer scriptMultisite support and cloud storage require a paid plan
WP All ImportChunked imports with resume and retry supportImage downloading is available only in the Pro version
WP-CLIRuns imports outside the browserRequires SSH access to the server

Tools That Avoid Remote Media Fetching Entirely

All-in-One WP Migration is the one most people reach for, and ServMask’s free tier stops at a 512MB import, which is nothing for a photo-heavy site.

Duplicator sits above 1M active installations and builds a single archive plus a standalone installer, so the destination does not even need WordPress running yet.

UpdraftPlus is installed on more than 3 million sites and restores uploads straight from an existing backup set, which is handy when the source is already gone.

Tools That Retry and Resume Failed Media Downloads

WP All Import reports 200,000+ active installs and splits files into chunks automatically, so a 50,000-row feed does not die at row 400.

The catch nobody mentions upfront: downloading images from external URLs is a Pro feature, listed in WP All Import’s own version comparison alongside scheduling and FTP sources.

WP-CLI is the free equivalent. Running wp import through the wordpress-importer package sidesteps browser timeouts and PHP web limits, which quietly solves most large-file failures.

How to Fix Failed Media Imports in Theme Demo and Page Builder Kit Installs.

Raise the PHP limits the theme vendor publishes, deactivate everything except the importer, then run the demo import a second time. Most one-click importers skip already-imported items, so the second pass picks up only what failed.

Starter Templates alone runs on 2M+ sites, and its own documentation is the fastest route to the right numbers.

SettingStarter Templates guidance
memory_limit512M
max_execution_time900
post_max_size256M
upload_max_filesize720M

Astra’s system requirements set the floor lower: 128MB of WP memory minimum, 256MB preferred, plus a note about raising SubstituteMaxLineLength to 10M when Starter Templates is involved.

The Ones That Are Not Actually Errors

Envato states it plainly for Elementor Template Kits: the kits are page layouts, and you are expected to replace the images unless you hold an Envato subscription covering the premium photos.

Grey placeholder boxes after a kit import are usually licensing, not a broken fetch. Check the kit’s item page before you spend an hour on server settings.

Elementor’s own bug tracker documents a related quirk where image URLs without an explicit file extension import as placeholders while identical files with extensions upload fine.

What to Do Before the Second Attempt

  • Deactivate every plugin except the theme, the page builder, and the importer
  • Confirm cURL is enabled under Tools > Site Health > Info > Server
  • Run Elementor > Tools > Regenerate CSS if layouts look broken rather than empty
  • Use Elementor’s Replace URL tool to repair image paths after a partial import

Wordfence and caching plugins are the usual culprits when the template library will not connect at all, a point the Starter Templates troubleshooting docs make directly.

If the import kills the site outright rather than skipping media, you are looking at a white screen problem, and the fix is memory rather than media. A demo that half-installs and leaves the theme broken points at theme installation errors instead.

How to Fix Failed Image Imports in WooCommerce Product CSV Uploads

Put full, publicly reachable URLs in a column named images, separated by commas, with the featured image first. WooCommerce downloads each one into the media library, because external images cannot serve as featured images or gallery items.

WooCommerce holds roughly 31% of the ecommerce market per WPZOOM’s July 2026 figures, so this specific import path gets a lot of traffic and a lot of tickets.

The separator trips people constantly. The built-in importer expects commas inside quotes. WooCommerce’s Product CSV Import Suite documentation calls for a vertical pipe instead.

Why Individual Rows Fail

Commas inside filenames: a documented WooCommerce bug (issue 24110) truncates image URLs at the comma and then reports the shortened path as missing.

Blocked remote fetches: WebToffee’s troubleshooting guide attributes most “error getting the remote images” entries to the image host refusing the request.

Duplicate SKUs: a collision skips the row without a loud failure, so the product exists and the image never arrives.

Rejected file types: the same “not permitted for security reasons” message from the media library shows up in the import log.

The Faster Route for Big Catalogues

Upload the images to wp-content/uploads first, then reference just the filename (sneakers.jpg) in the images column rather than a full URL. WooCommerce matches it against the library and skips the download entirely.

That single change removes remote fetching from the equation and stops WordPress creating sneakers-1.jpg, sneakers-2.jpg copies of images shared across variations.

Test 5 products before you run 5,000. Then verify in Products > All Products, where the image column tells you the truth faster than any log file.

How to Prevent Failed Media Imports on the Next Migration

Move the uploads folder by FTP first, raise the limits before you start, and keep the source site live until the destination is verified. Those three habits remove the conditions this error needs to exist.

WordPress.org’s own importer documentation recommends splitting a large export into smaller pieces when memory becomes the constraint, and WXR File Splitter handles that in a couple of clicks.

The Pre-Migration Checklist

  • Keep the old site reachable until the new one is confirmed, not merely started
  • Copy wp-content/uploads across before running the XML import
  • Confirm the raised limits in Site Health rather than trusting the edit
  • Deactivate security plugins and put Cloudflare in Development Mode for the duration
  • Generate a fresh export instead of reusing one from three months ago

Development Mode expires automatically after three hours, which is usually longer than the import and short enough that you cannot forget about it.

Verifying the Import Actually Worked

Count attachments on both sides. Run SELECT COUNT(*) FROM wpposts WHERE posttype = ‘attachment’ on the source and the destination, then compare.

Matching numbers mean the records exist. It does not prove the files do, so spot-check a handful of images in the media library grid view before you call it finished.

Understanding how WordPress stores content in the database makes that query far less intimidating than it looks.

Last thing, and I say this as someone who has skipped it and regretted it: take a backup of the destination before every import attempt. Failed imports leave partial data behind, and the second run inherits the mess from the first.

FAQ on Failed To Import Media WordPress

Why does WordPress say failed to import media?

The WordPress Importer read an attachment URL from your WXR file, tried to download it, and could not save the result into wp-content/uploads. The cause sits on the source site, your server, or the network between them.

Did my posts import if the media failed?

Usually yes. Post content, categories, and custom fields land normally while the attachment records and physical files do not, which is why the media library looks empty after an otherwise successful migration.

How do I see the real reason behind the error?

Add define(‘IMPORTDEBUG’, true); to wp-config.php, then re-run the import. The short message turns into a specific failure: a 404, a timeout, a permission problem, or a rejected MIME type.

Can I fix this if the old site is already offline?

Not through the importer. It downloads each file from a live URL, so a dead source means the media has to come from a backup or an existing copy of the uploads folder.

Which PHP settings stop media imports?

Four do most of the damage: memorylimit, maxexecutiontime, uploadmaxfilesize, and postmaxsize. Set them to 256M, 300, 128M, and 128M, then confirm the values in Site Health.

Do file permissions really cause this?

Yes, and quietly. If wp-content/uploads is not writable by the PHP process user, the write fails with no useful error. Directories belong at 755, files at 644, never 777.

Why did images import as broken or tiny files?

Cloudflare or a security plugin returned a challenge page with a 200 status. The importer saved that HTML as the image, producing valid-looking files of 4KB that display as nothing.

How do I import media without the WordPress Importer?

Copy wp-content/uploads across by FTP, keeping the year/month folder structure. Register the files with Add From Server, then run wp media regenerate to rebuild the thumbnails.

Why do theme demo images arrive as grey placeholders?

Licensing, not a failed fetch. Envato states that Elementor Template Kits ship as layouts and expect you to supply your own photos unless you hold a subscription covering the originals.

Why do WooCommerce CSV product images fail?

Usually the images column. URLs must be public and absolute, commas inside filenames break the parse, and duplicate SKUs skip the row silently. Referencing local filenames instead avoids remote fetching entirely.

Conclusion

The failed to import media error in WordPress has a short list of suspects, and one browser test tells you which one you are dealing with before you touch a single setting.

Open a failing attachment URL. A dead link means the source is your problem. A loading image means the server or the network in between is.

From there the work is mechanical: raise the PHP limits, correct ownership on the uploads directory, pause the firewall, re-run.

For libraries over a gigabyte, stop fighting the importer. Move the folder across by FTP and register the orphaned attachments afterwards.

  • Test one URL before editing anything
  • Read debug.log before you touch php.ini
  • Back up the destination between attempts

Migrations rarely fail twice for the same reason.