How many products are actually in my Shopify CSV?

Count distinct handles, not rows. Repeated handles are variants and image rows of one product, and the two numbers differ by roughly half on real supplier files.

What you are seeing

You need to know your catalogue size — for a plan, a quote, or a sanity check after an import — and every tool gives a different number.

There is no error message for this one. That is the problem, not an omission on this page — the import reports success and the damage is only visible if you go looking for it.

Why it happens

In a Shopify product CSV, a repeated Handle means "same product, next row". Those extra rows are variants, additional images, or both. Measured across 21 real supplier files and 19,885 rows, one row averages 0.574 products.

This is also why a post-import product count can look wrong when nothing went wrong: you compared a row count against a product count. And it is why a genuine loss — two products merged by a handle collision — hides easily, because you were already expecting the numbers not to match.

How to fix it

  1. Count distinct values in the Handle column. That is your product count.
  2. Count rows where the Handle column is non-empty for your record count.
  3. Compare handles before and after an import, not counts. A set difference names what is missing; a count difference only tells you something is.

Where this came from

We broke a real Shopify store on purpose to answer these questions, and kept what it said. Nothing on this page is quoted from documentation.

  • Across 21 real supplier files and 19,885 rows, 1 row = 0.574 products. A repeated Handle column is Shopify saying "same product, next variant", so a row count and a product count are different numbers about the same file.
  • A file whose preview promised 5 products and 6 SKUs produced 3 products, under a "Products imported" banner, with no error, no warning and no mention of the two that did not arrive. Both collision shapes collapsed: rows sharing a handle in two separate places in the file, and two DIFFERENT strings that normalise to the same handle.

What we did not measure. The 0.574 average comes from our corpus and the distribution is bimodal — files are mostly one-row-per-product or mostly multi-variant, with few in between.

Observed 2026-09-05. The store this was measured on has since been deleted, so these answers are an archive rather than something we re-run — we would rather tell you the date than imply it is checked continuously.

Check your file before you upload it

The Pre-Flight Report reads your supplier file and names every blocker, with the row it is on, before you go near an importer. It is free, it needs no account, and it does not send your file to a model.

Check a file free