How to split a crm contact csv into import batches
- Step 1Export the source contact list as CSV — Export from the system you are migrating from — old CRM, spreadsheet, or marketing platform. Make sure the export's column order matches the field mapping you will use on import.
- Step 2Dedup and validate before splitting (recommended) — The splitter copies duplicate and malformed rows into batches. Run the csv-deduplicator to collapse case-different email duplicates and the csv-validator for row-width and encoding issues, then split the clean result so each batch imports without per-row rejections.
- Step 3Drop the contact CSV onto the splitter — PapaParse reads it in your browser and auto-detects the delimiter. The first 10 rows preview so you can confirm the header matches your intended CRM field mapping before splitting.
- Step 4Set Rows per chunk to your CRM's import size — Type the per-import row count into the single Rows per chunk field (default 1000, minimum 1). For Salesforce's Data Import Wizard, 50,000 is the per-import ceiling; for HubSpot, choose a size that imports reliably and is easy to retry.
- Step 5Click Split into chunks — The result panel shows total contacts, number of batches, and rows per batch, then one line per batch with its
rows X–Yrange — handy for tracking which cohort went into which import. - Step 6Download and import each batch with the same field mapping — Each batch has its own Download button (no zip). Files are
contacts.part-N-of-M.csv, header included, so you reuse the same field mapping for every import. Import them in priority order.
Split behaviour for CRM imports
One option; the rest is fixed split logic. Confirm it matches your CRM's import expectations before a migration run.
| Behaviour | How it works | Why it matters for CRM imports |
|---|---|---|
| Rows per chunk (only option) | Number input, min 1, default 1000; consecutive blocks | Size to your CRM's per-import limit; batch count is derived |
| Header in every batch | Source row 1 copied to each file's top | Reuse one field mapping for all batches — no mis-mapped properties |
| Order preserved | Contacts keep source order; no re-sort | A lead-score-sorted list keeps high-value cohorts grouped |
| Remainder in last file | Final batch holds leftover contacts | 300,000 at 50,000/chunk → six even files |
| No dedup / no edits | Duplicate and malformed rows copied verbatim | Dedup and validate upstream; the splitter only cuts |
| Quote-aware | Quoted commas/newlines kept within a record | Acme, Inc. stays one company field, never two columns |
Batch maths for migration lists
Worked examples (data rows excluding the header). The row splitter is a Pro tool capped at 100,000 rows / 100 MB per file; Free caps at 500 rows / 2 MB.
| Contacts | Rows per chunk | Batches | Last batch | Note |
|---|---|---|---|---|
| 300,000 | 50,000 | 6 | 50,000 | Source over Pro 100k/file ceiling — pre-split at export |
| 90,000 | 50,000 | 2 | 40,000 | Salesforce Import Wizard size (50k/import) |
| 90,000 | 30,000 | 3 | 30,000 | Even, three HubSpot imports |
| 100,000 | 25,000 | 4 | 25,000 | At the Pro per-file ceiling |
| 480 | 100 | 5 | 80 | Within Free row cap, but tool is Pro-gated |
Cookbook
Before/after examples from CRM migrations. Contact data illustrative; the splitter never alters cell contents.
300k migration into 50k import files
ExampleA full CRM cutover. Split the master list into 50,000-contact files and import each with the same field mapping, retrying only a failed batch.
Input: master-contacts.csv (300,000 rows + header) → exceeds Pro 100k/file ceiling, so pre-split at export into 100k files first, then per file: Rows per chunk: 50000 Each 100k file → 2 batches of 50,000 (header in each): master-contacts.part-1-of-2.csv master-contacts.part-2-of-2.csv
Header copied so field mapping is reusable
ExampleHubSpot and Salesforce map CSV columns to CRM properties via the header. A headerless batch breaks the mapping. The splitter copies the header into each chunk.
Source: Email,First Name,Company,Phone a@x.com,Ann,Acme,555-0100 b@x.com,Bo,Globex,555-0101 c@x.com,Cy,Initech,555-0102 Rows per chunk: 2 → part-1-of-2.csv part-2-of-2.csv Email,First Name,Company,Phone Email,First Name,Company,Phone a@x.com,Ann,Acme,555-0100 c@x.com,Cy,Initech,555-0102 b@x.com,Bo,Globex,555-0101
Company name with a comma stays intact
ExampleQuoted company names survive the split, so a comma inside the name never spills into the next column in any batch.
Source row: d@x.com,Dee,"Acme, Inc.",555-0103 After split (whichever batch it lands in): d@x.com,Dee,"Acme, Inc.",555-0103 → Company stays one field; HubSpot/Salesforce map it correctly.
Dedup-then-split for a clean import
ExampleThe splitter does not dedup. Case-different email duplicates would be spread across batches and create duplicate CRM records. Dedup first.
Raw export: 90,120 rows incl. 120 case-different email dupes Step 1 csv-deduplicator (case-insensitive) → 90,000 rows Step 2 csv-row-splitter, 30000/chunk → 3 clean files Skip step 1 and HubSpot/Salesforce create or merge duplicate contacts across the three imports.
Priority cohort imported first
ExampleSort the list by lead score before splitting, then import batch 1 (highest scores) first so sales engages top leads while later batches load.
Step 1 csv-sorter → sort by lead_score descending Step 2 csv-row-splitter, 25000/chunk Part 1 = top 25,000 leads (rows 1–25000) → import Part 1 first; remaining batches follow.
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.
Duplicate contacts spread across batches
By designThe splitter does not dedup. Case-different email duplicates (Sue@x.com vs sue@x.com) or repeated rows are copied verbatim and may land in different batches, creating duplicate CRM records or unexpected merges. Dedup with the csv-deduplicator before splitting.
Salesforce Data Import Wizard 50k limit
Plan limitThe Salesforce Data Import Wizard accepts up to 50,000 records per import; larger files need Data Loader. Set Rows per chunk to 50,000 (or lower) so each batch fits the Wizard, or split smaller for easier retries.
Field mapping mismatch between batches
Cannot happenBecause the header is copied identically into every chunk, all batches share the same columns in the same order — so you reuse one field mapping for the whole migration. The splitter never reorders or renames columns. If you need column changes, do them upstream with the csv-header-rename before splitting.
List over the 100,000-row Pro ceiling
Plan limitPro processes up to 100,000 rows / 100 MB per file. A 300,000-contact master list exceeds it — pre-split the source into sub-100k files at the export step, then batch each for import.
Blank rows in the export
PreservedEmpty lines are kept as rows, not skipped, so a blank separator counts toward the total and lands in a batch as an empty contact — which CRMs reject or import as a junk record. Strip them with the csv-empty-row-remover first.
Header-only file
ExpectedA file with the header and no contacts produces zero chunks (total rows 0). If you expected batches, confirm the export actually contains contacts.
Order is not changed
PreservedThe splitter does not sort — chunk 1 is the first N rows in source order. To import priority cohorts first, sort by lead score or owner with the csv-sorter before splitting.
Output without BOM
By designChunks are plain UTF-8 with no byte-order mark. CRM importers handle this fine; only a human opening a batch in Excel-on-Windows might see accented names render oddly — a display quirk, not a data error.
Many batches, individual downloads
ExpectedThere is no 'download all' zip — each batch downloads on its own button. A 300k migration split into six files means six downloads, which doubles as an import checklist.
Frequently asked questions
Does each batch include the header row?
Yes. The source header is copied to the top of every chunk, so you reuse one field mapping for every import and email, company, and phone always map to the right CRM property.
What is the Salesforce Data Import Wizard row limit?
Up to 50,000 records per import via the Wizard; larger files need Data Loader. Set Rows per chunk to 50,000 or lower so each batch fits the Wizard.
Can I choose the number of batches instead of rows per batch?
No. The only option is Rows per chunk. Batch count is total contacts ÷ chunk size, rounded up. For exactly N batches, set the chunk size to total contacts ÷ N.
Does the splitter remove duplicate contacts?
No. It is a pure cut and never dedups. Case-different email duplicates would spread across batches. Dedup with the csv-deduplicator before splitting.
Will every batch use the same field mapping?
Yes, because the header is copied identically into each chunk, all batches share the same columns in the same order — so one field mapping covers the whole migration.
Does it keep contacts in priority order?
It preserves source order. Sort by lead score or create date with the csv-sorter before splitting if you want to import high-value cohorts first.
How are the batch files named?
Each chunk is the source filename plus a part suffix, like contacts.part-1-of-6.csv, sorting in import order.
Can I download all batches at once?
No. Each batch has its own Download button and saves individually — there is no zip bundle.
Is contact PII uploaded anywhere?
No. Parsing and splitting run in your browser; names, emails, phone numbers, and deal data never reach a server.
What is the largest list I can split?
The row splitter is a Pro tool: up to 100,000 rows / 100 MB per file. A larger master list should be pre-split into sub-100k files at export.
What happens to company names with commas?
They stay intact. Quoted fields are parsed quote-aware, so a comma inside Acme, Inc. never becomes a column break in any batch.
Should I rename headers before or after splitting?
Before. Rename columns once on the source with the csv-header-rename, then split, so every batch carries the corrected headers.
Privacy first
Processing runs locally in your browser with PapaParse. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.