Which cause is yours?
| What you observe | Likely cause |
|---|---|
| Products import, but have no image or the importer reports an invalid image type | 1. A share link that returns a preview page, not the image |
| The URL opens on your computer, but the import log reports an error getting the remote image | 2. The image server refuses requests from your store's server |
| You put file names into Images after uploading by FTP, and nothing is attached | FTP files are not Media Library items |
| The supplier's Excel file shows photos, but the CSV saved from it has no images | 3. Pictures embedded in the workbook (not text, so not in a CSV) |
| The import stops partway with a 504, a timeout or a memory error | 4. Downloading and resizing many large images in one run |
How WooCommerce reads the Images column
The values are separated by commas; the first is the main image, the others go to the gallery. A value with :// is treated as a URL: if no attachment from that URL exists yet, the store's server downloads it. Any other value is treated as a file name and looked up among the attachments of the Media Library.
| Record | Type | SKU | Name | Regular price | Images |
|---|---|---|---|---|---|
| 1 | simple | MUG-01 | Mug | 12.00 | https://cdn.example.com/products/mug-front.jpg, https://cdn.example.com/products/mug-back.jpg |
| 2 | simple | MUG-02 | Mug large | 14.00 | mug-large.jpg |
Record numbers exclude the header. (empty) marks an empty cell; · marks outer spaces and ↵ a line break.
- Uploaded with Media → Add New (or
wp media importin WP-CLI): the file is an attachment, so its file name in Images is found. - Copied to
wp-content/uploadsby FTP: the file exists on disk but is not registered in the Media Library, so a bare file name is not found. Use the file's full public URL instead (WooCommerce then downloads it and creates an attachment), or register the files first. - A local path such as
C:\Photos\mug.jpgor afile://link cannot work: the store's server has no access to your computer.
CatalogDock lists the values of your Images column by kind (URL, file name, local path, other) without changing them, so such problems are visible before the import.
1. Cloud storage share links (Google Drive, Dropbox, OneDrive)
A share link usually opens a web page with a preview of the file. When the store downloads it, it gets HTML instead of image bytes, and the image is refused.
- Dropbox: a link ending in
dl=0opens the preview page; withdl=1Dropbox answers with a download instead. Test the changed link from the store's server (below) before relying on it. - Google Drive and OneDrive: share links point to a viewer. Download endpoints can ask for a confirmation, limit the number of requests and give no file name in the URL, so they fail unpredictably in bulk imports.
Reliable fix: upload the images to your Media Library, your own server or an image host that serves the file itself at a public URL ending in the file name, and use those URLs or file names in Images.
2. 403 Forbidden & CDN hotlink protection
Opening a URL in your browser proves only that your computer can get it, with your cookies, IP address and browser. The import downloads from your store's server with the WordPress HTTP API, whose default user agent looks like WordPress/7.1; https://your-store.example. A supplier's CDN, firewall or hotlink protection can refuse exactly those requests (403, 401, a challenge page or a redirect to HTML).
Test it the way the store does
Run a GET request on the store's server (for example over SSH; ask your host if you have no shell access), not on your computer. A header-only request (curl -I, HEAD) is not enough: some servers answer HEAD differently from the GET the import makes.
curl -sS -L -o /dev/null \
-A "WordPress/7.1; https://your-store.example" \
-w "%{http_code} %{content_type} %{size_download}\n" \
"https://supplier.example/images/12345.jpg"Solutions
- Ask the supplier for an image archive or a feed meant for resellers, or to allow your store's server.
- Host the images yourself: upload them to your Media Library (Media → Add New) or to your own server, then reference those file names or URLs in Images.
3. Embedded Excel cell pictures (OpenXML DrawingML)
A CSV is plain text. When a workbook with product photos is saved as CSV, the photos are not written: the Images column stays empty unless the supplier also typed image URLs into a column.
Excel stores pictures in two different ways, and they need different handling:
- Pictures placed over cells (Insert → Pictures → Place over Cells) are DrawingML drawings anchored to a position on the sheet. CatalogDock can read these in your browser and find the row under each picture from its anchor.
- Pictures placed in a cell (Place in Cell) and
IMAGE()formulas are cell values (rich data). CatalogDock reports them but does not extract them.
What CatalogDock does with pictures over cells
- One picture on one product row is linked to that row's SKU.
- Several pictures on a row, a picture across several rows, or a picture at a fixed position on the sheet: you choose the row (or not to link it). Nothing is guessed from file names or order; a picture left undecided goes into the manifest as
needs_confirmation, without a SKU. - It builds a ZIP with the original image files and
manifest.csv(file → SKU, row, cell, how it was linked).
The ZIP is not an import. The Images column of your CSV is not filled in. After downloading it:
- Upload the image files to your Media Library (Media → Add New) or to your own image host.
- Using
manifest.csv, write the uploaded file names or public URLs into the Images column of each product (first value: main image). - Check the file again, then import it on a staging copy of your store.
More detail: Extract embedded images from Excel cells.
4. Timeouts & thumbnail generation memory exhaustion
For each new image the store downloads the file and WordPress creates several resized copies (the number depends on your theme and plugins). Large originals and many gallery images per product make each row slow and memory-hungry, which can end the import with a 504, a timeout or an Allowed memory size exhausted error in the PHP log.
How to reduce the risk
- Resize the originals before uploading them; product photos rarely need 4000 px.
- Import in smaller files. CatalogDock can split a catalog into import batches that keep each parent with its variations; a product group larger than the target stays whole in one file. Smaller files lower the risk; they do not remove the hosting limits.
- Read the error log or ask your host which limit was hit (time, memory or proxy timeout) before changing settings. See WooCommerce import 504 timeout.
- If an import stopped, missing resized copies can be created later with
wp media regenerate --only-missing(WP-CLI).
Reported for you to decide
- The kind of every value of the Images column: web URL, Media Library file name or a local path the importer cannot use.
- Pictures placed over cells of an Excel sheet, extracted with their row and SKU; ambiguous ones wait for your confirmation.
Needs data from your store
Whether your store's server can download a URL and whether a file name exists in your Media Library. The free WordPress plugin uploads the Excel pictures you choose to the Media Library and writes their URLs into the CSV.
Still failing? Related guides
- WooCommerce import referenceColumns, checks and limits of the WooCommerce import in one place.
- The import stops or times out504 errors, server limits and variation-safe batches.
- Invalid or duplicated SKUIdentify the conflicting product or source value.
- Variations are missing or unlinkedReview parents, order, attributes and prices.
Check your product files before importing
CatalogDock validates your CSV, lists the values of the Images column by kind and extracts pictures placed over cells from Excel files, in your browser, before anything reaches your store. It does not prove that your store's server can download a URL.
Runs in your browser · No files uploaded · Never connects to your store
Applies to the built-in WooCommerce CSV importer (Products → Import); importer behavior as in WooCommerce 11.1.2 (on WordPress 7.1.2). Other importers and image plugins behave differently.