How to sort a product csv by price, lowest first
- Step 1Export the product feed as CSV — Shopify: Products → Export → plain CSV. Google Merchant Center: your feed source file, or Products → download. Amazon: category/inventory template (tab-delimited — auto-detected). Wholesale / ERP: most export a comma- or semicolon-delimited price list; all are auto-detected.
- Step 2Drop the file onto the sorter above — The first row is read as the header and stays pinned to the top. The Sort by column dropdown fills with your column names (
Price,variant_price,MSRP,Cost), so you pick the price field by name. - Step 3Select the price column — Choose your price field in the dropdown. If your feed has several price-like columns (
Price,Compare-at price,Cost per item), pick the exact one you want to order by — the sort uses one column per pass. - Step 4Tick the Numeric sort checkbox — this is the critical step — Enable Numeric sort (treat values as numbers). Without it, prices sort as text and
$1,299.00lands before$9.99. With it, currency symbols and thousands separators are stripped so values compare as real numbers —$9.99correctly sorts below$1,299.00. - Step 5Leave ascending selected for lowest-first — Keep A → Z (ascending) so the smallest price sorts to the top. For a highest-price-first view (premium products on top), switch to Z → A (descending) instead — same numeric mode, opposite direction.
- Step 6Sort, check the cheapest row, and download — Click Sort rows. The result panel confirms
Sorted by <price column> · ascendingand the row count. Verify the top row really is your cheapest product, then Download Sorted CSV — the file saves as<name>.sorted-asc.csv.
How numeric mode parses common price strings
Numeric sort strips every character except digits, . and -, then runs parseFloat. This is exactly how the tool reads each cell before comparing — values that can't parse are treated as 0.
| Price cell in the feed | After stripping non-numeric | Compared as | Sorts correctly? |
|---|---|---|---|
$9.99 | 9.99 | 9.99 | Yes |
$1,299.00 | 1299.00 | 1299 | Yes — comma stripped |
£12.50 | 12.50 | 12.5 | Yes — currency symbol stripped |
1.299,00 (EU decimal comma) | 1.299 then parseFloat reads 1.299 | 1.299 | No — reads as ~1.30, not 1299. Normalise first |
-5.00 (credit/adjustment) | -5.00 | -5 | Yes — minus kept, sorts below 0 |
Call for price (text) | `` (empty) | NaN → treated as 0 | Sorts among the zero/blank group |
| `` (blank) | `` (empty) | NaN → 0 | Groups with other blanks at the bottom (asc: top) |
Alphabetic vs numeric sort on the same price column
Why the Numeric checkbox is non-optional for price columns. Same 4 prices, ascending, both modes.
| Input order | Alphabetic (numeric OFF) — wrong | Numeric (numeric ON) — correct |
|---|---|---|
$9.99, $1,299.00, $149.00, $15.00 | $1,299.00, $149.00, $15.00, $9.99 | $9.99, $15.00, $149.00, $1,299.00 |
| Why | Text compare: 1 < 9, so $1,... first | Number compare: 9.99 < 15 < 149 < 1299 |
Cookbook
Real before/after snippets from product feeds. SKUs and prices illustrative; the parsing behaviour is exactly what the tool does.
Currency-formatted prices, lowest first
ExampleA Shopify export with $ and thousands separators. Numeric sort strips both before comparing, so the order is by actual price. The displayed price string is untouched in the output.
Input: SKU,Title,Price A-100,Premium Stand,"$1,299.00" A-101,Cable,$9.99 A-102,Bundle,$149.00 Sort by: Price · A -> Z (ascending) · numeric ON Output (cheapest first, formatting preserved): SKU,Title,Price A-101,Cable,$9.99 A-102,Bundle,$149.00 A-100,Premium Stand,"$1,299.00"
The classic mistake: numeric checkbox left off
ExampleThe same feed sorted ascending with Numeric OFF. Text comparison puts the four-figure price on top because '1' precedes '9'. Always tick Numeric for price columns.
Input: SKU,Price A-100,$1299 A-101,$9.99 A-102,$149 Sort by: Price · ascending · numeric OFF (WRONG for prices) Output (scrambled by text order): SKU,Price A-100,$1299 <- most expensive, but sorts first as text A-102,$149 A-101,$9.99 Fix: re-run with the Numeric sort checkbox ON.
EU decimal-comma prices need normalising first
ExampleA European feed writes 1.299,00 (dot thousands, comma decimal). Numeric mode strips the comma and keeps the dot, so 1.299,00 becomes 1.299 and parses as ~1.30 — wrong. Convert to dot-decimal first with csv-find-replace, then sort.
Input (EU format): SKU,Price B-1,"1.299,00" B-2,"9,99" Direct numeric sort would read 1.299 (~1.30) and 9,99 -> 9 => wrong order. Step 1 - csv-find-replace: remove '.' thousands, then ',' -> '.' find: \. (in price col) replace: (nothing) find: , replace: . -> 1299.00 and 9.99 Step 2 - csv-sorter: Price · ascending · numeric ON Output: 9.99 then 1299.00
Highest price first (premium products on top)
ExampleSame numeric mode, descending direction — useful for merchandising a 'premium' collection or auditing the top of your price range.
Input: SKU,Price C-1,$24.00 C-2,$499.00 C-3,$89.00 Sort by: Price · Z -> A (descending) · numeric ON Output (most expensive first): SKU,Price C-2,$499.00 C-3,$89.00 C-1,$24.00 (downloads as <name>.sorted-desc.csv)
Same-price products keep their feed order (stable)
ExampleTwo SKUs at $19.99. The stable sort keeps them in the order the feed had, so a feed already ordered by SKU stays SKU-ordered within each price band.
Input (ordered by SKU): SKU,Price D-1,$19.99 D-2,$19.99 D-3,$9.99 Sort by: Price · ascending · numeric ON Output ($19.99 pair keeps D-1 before D-2): SKU,Price D-3,$9.99 D-1,$19.99 D-2,$19.99
Errors and edge cases
Real errors and silent failures sourced from each platform's own documentation. Match the wording to the row, fix what the row says to fix.
Numeric checkbox left off — prices sort as text
Invalid orderWithout Numeric sort, the price column compares character by character, so $1,299.00 sorts above $9.99 (because 1 < 9). The result looks sorted but is meaningless for prices. Always tick Numeric sort for any money column. This is the number-one mistake when sorting product feeds.
EU decimal-comma format (`1.299,00`)
Invalid orderNumeric mode strips everything except digits, . and -. For 1.299,00 it removes the comma and keeps the dot → 1.299, which parseFloat reads as roughly 1.30, not 1299. European-locale feeds must be normalised to dot-decimal first with csv-find-replace (remove the thousands ., then turn the decimal , into .).
Negative or zero prices (credits, free items)
Sorted correctlyNumeric mode keeps the minus sign, so -5.00 (a credit or adjustment line) sorts below 0.00. Free items at 0 sort to the bottom of a descending sort and the top of an ascending one — as expected. No special handling needed.
`Call for price` / non-numeric price text
Grouped at zeroA cell like Call for price strips to an empty string; parseFloat returns NaN, which the tool treats as 0. All such rows group together at the 0 position (top in ascending, near the bottom in descending). The rows are preserved — nothing is dropped. If you want them excluded, filter first with csv-column-filter.
Blank price cells
Grouped at zeroEmpty price cells also parse to 0 in numeric mode, so they cluster with the Call for price group. In ascending order they appear near the top; in descending, near the bottom. To pull blank-priced rows out entirely, use csv-column-filter with an is-empty condition before sorting.
Mixed currencies in one column (`$`, `£`, `€`)
Compares numbers onlyNumeric mode strips the symbol and compares the bare number, so €10 and $10 both compare as 10 — the sort ignores currency entirely. If your feed mixes currencies in one price column, the numeric order won't reflect true value. Split by currency first (or convert to one currency) before sorting; the sorter has no exchange-rate awareness.
Price stored with a trailing unit (`9.99/kg`)
Parses leading numberFor 9.99/kg, numeric mode strips the letters, leaving 9.99/ → parseFloat reads the leading 9.99. That usually sorts correctly, but 12/24 (a pack size) would strip to 12/24 and parse 12. Inspect feeds with embedded units; if the unit varies, normalise the column with csv-find-replace first.
File over 2 MB on the free tier
Rejected (limit)A full marketplace catalogue often exceeds 2 MB; the free tier blocks before sorting and shows a Pro overlay. Pro raises the cap to 100 MB. For a one-off free run, split the feed with csv-row-splitter and sort each chunk.
More than 500 rows on the free tier
Rejected (limit)Free sorts up to 500 result rows; a larger catalogue is blocked after parsing with a row-count message. Pro lifts this to 100,000 rows. Splitting then re-merging sorted chunks is possible but a single Pro sort is far cleaner for a real feed.
Frequently asked questions
Why is `$1,299` showing up before `$9.99` when I sort by price?
Because the Numeric sort checkbox is off, so prices are compared as text — and 1 sorts before 9. Tick Numeric sort (treat values as numbers) and re-run. Numeric mode strips the $ and the comma, compares 1299 vs 9.99 as real numbers, and $9.99 correctly sorts first.
Does numeric sort handle currency symbols and commas?
Yes. Numeric mode removes every character except digits, the decimal point, and the minus sign before comparing. So $1,299.00, £12.50, and 1299 all parse to their numeric value automatically — you don't need to strip the symbols yourself first (for US/UK formatting).
What about European prices like `1.299,00`?
Those need normalising first. Numeric mode treats . as the decimal point and strips ,, so 1.299,00 becomes 1.299 (~1.30), which is wrong. Use csv-find-replace to remove the thousands . and convert the decimal , to ., giving 1299.00, then sort with Numeric on.
Will sorting change my price formatting?
No. The sorter never edits cells — it only reorders rows. $1,299.00 stays exactly $1,299.00 in the output; numeric mode is used only for the comparison, not for rewriting the value. Your feed stays import-ready.
Can I sort by price and break ties by SKU?
The sorter does one column per pass, but its sort is stable, so do it in two passes: sort by SKU first, then sort by price with Numeric on. Within each price band, the SKU order is preserved. Always sort the tiebreaker column before the primary key.
How do I show the most expensive products first?
Keep Numeric sort on and switch the direction to Z → A (descending). The highest price sorts to the top. The file downloads as <name>.sorted-desc.csv so you can tell it apart from the ascending version.
What happens to products with no price or 'Call for price'?
In numeric mode they parse to 0 (the text strips to empty, parseFloat returns NaN which is treated as 0), so they group together — at the top in ascending order, near the bottom in descending. They're never dropped. To exclude them, filter with csv-column-filter first.
My feed is tab-delimited (Amazon template) — will it sort?
Yes. The delimiter is auto-detected, so comma, semicolon, and tab-delimited feeds all parse without configuration. The sorted file is written as standard CSV.
Is my pricing data sent to a server?
No. Everything runs in your browser via PapaParse — wholesale prices, margins, costs, and supplier SKUs never upload. When signed in, only a usage counter is recorded (no content). Safe for confidential pricing.
How big a product feed can I sort for free?
Free handles up to 2 MB and 500 rows per job. Pro raises that to 100 MB and 100,000 rows. For large catalogues on free, split with csv-row-splitter and sort each piece, or upgrade for a single pass.
Can I remove duplicate SKUs while sorting?
No — sorting never removes rows. Deduplicate first with csv-deduplicator (collapse repeated SKUs), then sort the clean feed by price. Each tool does one job; chaining them gives you a deduped, price-sorted feed.
Does mixing currencies in one column work?
Numeric mode strips the symbol and compares only the number, so €10 and $10 both read as 10 — currency is ignored. If your price column mixes currencies, the numeric order won't reflect real value. Convert to a single currency (or split by currency) before sorting.
Privacy first
Processing runs locally in your browser with PapaParse. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.