Pulse - Value Added
FRACTIONAL CRO · MARYLAND-BASED, NATIONWIDE · $0→$200M

Kory White

RevOps & Revenue Leadership

Get a 30-minute revenue checkup — Kory reviews your pipeline and forecast, then names the 1–2 fixes that move revenue fastest. 25 yrs scaling teams $0→$200M.

30-minute revenue checkup →
Hire a Fractional CROHow We Help?LinkedInRésuméCRO Syndicate
← Library
Knowledge Library · software
13/13 Gate✓ IQ Certified10/10?

How to import contacts and deals from a CSV file into HubSpot CRM without creating duplicates in 2027?

SoftwareHow to import contacts and deals from a CSV file into HubSpot CRM without creating duplicates in 2027?
📖 3,720 words🗓️ Published Aug 16, 2026
Direct Answer

Import contacts first, then deals, using HubSpot's multi-file import with email as the contact dedupe key and a unique Record ID or custom "Deal Key" property for deals. HubSpot deduplicates contacts automatically on email; deals have no native unique key, so you must supply one or duplicates will appear.

Two paths: HubSpot's native CSV importer versus a keyed sync through middleware

Almost every duplicate-free import decision comes down to two families of approach, and they fail in different places, so picking the wrong one costs you a cleanup project rather than an afternoon.

Path one — HubSpot's native import tool. You go to CRM → Contacts (or Deals) → Import → Start an import → File from computer, then choose "Multiple files with associations" when you want contacts and deals loaded together in one pass. HubSpot's importer has one genuinely strong deduplication behavior baked in: for contacts, Email is a unique identifier. If a row's email matches an existing contact, HubSpot updates that contact rather than creating a second one. The same is true of Record ID — HubSpot's internal object ID — which is the strongest match key available because it is exact, immutable, and never re-used. Companies dedupe on domain name and Record ID. Deals are the weak link: out of the box, the only unique identifier a deal has is Record ID. A deal name is not unique, an amount is not unique, a close date is not unique. If you import a CSV of 400 deals twice without Record IDs, you get 800 deals.

Path two — a keyed sync through middleware or the API. Instead of dropping the CSV into the importer, you route it through something that can look before it writes: HubSpot's own Operations Hub data sync, an iPaaS layer (Zapier, Make, Workato, Tray, Boomi), a reverse-ETL tool pointed at your warehouse, or a script hitting the CRM API directly. The distinguishing capability is the *search-then-decide* step. You query HubSpot for an existing record on whatever key you define, and only create when the search comes back empty. This is what lets you dedupe deals at all, because you can search on a custom property that the native importer would happily duplicate.

How to import contacts and deals from a CSV file into HubSpot CRM without creating duplicates in 2027 — figure 1

The trade-off is blunt. Native import is free, requires no engineering, handles associations in one file set, and is genuinely safe for contacts and companies. It is unsafe for deals, line items, and custom objects unless you carry Record IDs. Middleware costs money and setup time, but gives you idempotency — run the same file five times, end up with the same records five times.

There is a third, quieter option worth naming because teams reach for it and shouldn't: importing everything and cleaning up after with HubSpot's built-in "Manage duplicates" tool. That tool surfaces likely duplicate contacts and companies using a similarity score across email, name, and company, and lets you merge them in pairs. It does not scan deals. Merging is also lossy in ways people underestimate — the secondary record's timeline, some property values, and certain associations behave in ways that surprise you after the fact. Cleanup is a fallback, not a plan.

A fourth wrinkle: HubSpot's importer can also *associate* records during the same run. In a multi-file import you map a shared column — say Email on both the contacts file and the deals file — and HubSpot uses it to link each deal to the right contact. That association column is not a dedupe key. It tells HubSpot who to attach the deal to; it does not tell HubSpot whether the deal already exists. Teams conflate these two jobs constantly, and it is the single most common reason a "careful" import still produces duplicate deals.

How to decide between them

The decision is mostly a function of three variables: whether you're doing this once or repeatedly, whether you already have HubSpot Record IDs for the records, and whether deals are in scope at all.

How to import contacts and deals from a CSV file into HubSpot CRM without creating duplicates in 2027 — figure 2

If it's a one-time migration and you have no Record IDs (because these records have never been in HubSpot), a native import is fine — nothing exists to duplicate. The risk arrives on the second run, when someone re-imports a corrected file. That's when you need to have exported Record IDs from the first run and joined them back into your source file.

If it's a recurring feed — nightly deal exports from an ERP, weekly lead lists from a conference platform, monthly reconciliations from finance — the native importer is the wrong instrument. Every run is a fresh chance to duplicate. Build the keyed path once.

If deals are in scope and you can't guarantee a stable key, stop and create one before importing anything. This is the highest-leverage 20 minutes in the entire project.

How to import contacts and deals from a CSV file into HubSpot CRM without creating duplicates in 2027 — figure 3

One more decision input people skip: who owns the file. If a non-technical team member will run this import monthly, the native path with a saved column mapping and a pre-built key column is more reliable than a middleware scenario nobody but you understands. Operational durability beats technical elegance when the person on shift at 6pm has to make it work.

The concrete numbers behind each option

Native import limits. HubSpot's file import caps out at 1,048,576 rows and 512 MB per file — the row ceiling is Excel's limit, not a coincidence. A multi-file import accepts up to 10 files in a single run. Practically, nobody should push a million-row file through the UI in one go; splitting into chunks of roughly 20,000 to 50,000 rows makes failures survivable, because a failed 500,000-row import is a very bad afternoon and a failed 20,000-row chunk is a re-run. Import processing is asynchronous — a large file may take anywhere from a few minutes to over an hour to finish, and HubSpot emails you when it completes.

Column count and property creation. During mapping, any unmapped column can be turned into a new custom property on the spot. This convenience is a trap. It's how orgs end up with Phone, Phone Number, Phone_2, and Mobile Phone (old) as four separate properties. Before importing, map every column to an existing property or explicitly decide to skip it. Creating a property should be a deliberate act, not a byproduct of a Tuesday.

API rate limits. If you take the keyed-sync route, the CRM search endpoint is rate-limited and search results are capped — HubSpot limits how deep you can page through search results, so a naive "search every row one at a time" loop on 50,000 rows is both slow and likely to hit limits. The efficient pattern is the batch read endpoint: HubSpot supports batch reads of up to 100 records per call, and batch reads can look records up by a designated unique property, not just Record ID. That single capability — batch read by custom unique property — is the workhorse of duplicate-free deal imports at scale. Fifty thousand deals becomes 500 batch calls instead of 50,000 searches.

How to import contacts and deals from a CSV file into HubSpot CRM without creating duplicates in 2027 — figure 4

Custom unique properties. HubSpot supports marking a single-line text property as requiring unique values. There is a per-object cap on how many unique-value properties you can define, so treat those slots as scarce and spend one deliberately on your import key. Once a property is flagged unique, HubSpot enforces it at the platform level — a second record carrying the same value is rejected outright rather than quietly created. This is the difference between hoping for no duplicates and being structurally unable to make them.

Time budget, realistically. A clean contacts-only import of 10,000 rows: 30–60 minutes end to end if the file is already normalized, most of it spent on mapping and verification rather than upload. A contacts-plus-deals multi-file import with association columns: half a day the first time, an hour on repeat runs once the template exists. A keyed API sync built from scratch: one to three days of engineering for a solid, idempotent, logged implementation, plus a day of testing against a sandbox. Cleaning up 3,000 duplicate deals created by a bad import: multiple days, and some of it is unrecoverable because deal-level merging isn't available the way contact merging is.

Error rates worth planning for. In a typical export from a legacy system, expect somewhere between 2% and 15% of rows to have a problem that matters: missing email, malformed date, currency symbol inside an amount field, an owner email that doesn't correspond to a HubSpot user, or a pipeline stage name that doesn't exist in the target pipeline. Every one of those either fails the row or silently creates something wrong. HubSpot returns a downloadable error file listing failed rows and reasons — that file is the most useful artifact of the whole process and most people never open it.

How to import contacts and deals from a CSV file into HubSpot CRM without creating duplicates in 2027 — figure 5

Implementation: the sequence that actually prevents duplicates

Here is the working order. It's deliberately front-loaded — nearly all the duplicate prevention happens before a single row is uploaded.

Step one — export what already exists. Before importing anything, export your current HubSpot contacts and deals *including Record ID*. You want to know what you're walking into. Run a quick count: how many contacts share an email? How many deals share a name plus amount plus close date? That last query is your baseline duplicate rate, and you'll want it later to prove the import didn't make things worse.

Step two — normalize the source file. Lowercase and trim all emails; leading spaces and mixed casing are a leading cause of "HubSpot didn't dedupe" complaints, though HubSpot does normalize email casing for matching. Strip currency symbols and thousands separators from amounts. Convert dates to a single unambiguous format and confirm which order the importer expects, because 03/04/2027 is two different days depending on who exported it. Resolve owner emails against actual HubSpot users. Verify every pipeline and deal stage name matches the target pipeline exactly — HubSpot matches stage by label, and a stage that doesn't exist fails the row.

Step three — build the deal key. This is the step that does the real work. Create a single-line text property on the Deal object called something like External Deal ID or Deal Key, and mark it as requiring unique values. Then populate it in your CSV. If your source system has its own opportunity ID, use it verbatim — that's the ideal case. If it doesn't, construct a deterministic key by concatenating fields that together identify the deal: account identifier, plus a normalized deal name, plus close date, for instance ACME-2027-renewal-20270315. The requirement is determinism: the same source row must produce the same key every single time you regenerate the file, forever. A key built from a timestamp or a row number is not a key.

How to import contacts and deals from a CSV file into HubSpot CRM without creating duplicates in 2027 — figure 6

Step four — dry-run on a slice. Take 20 to 50 rows, including at least a few you know already exist in HubSpot, and import just those. Then check: did the known-existing records update rather than duplicate? Did the associations land? Did every property populate where you expected? Fix, and only then run the full file. Sandbox accounts are available on higher HubSpot tiers and are the right place for this, but a 25-row slice in production is a reasonable substitute when you don't have one.

Step five — run the real import with the right settings. In multi-file import, the contacts file and the deals file each get their own mapping, and you designate the common column that links them. Map Email on contacts. Map your unique Deal Key on deals. Map Record ID wherever you have it — it always wins over any other key. If HubSpot offers a choice about whether to overwrite existing values with blanks, be deliberate: an unchecked blank-overwrite setting is how a good import erases three years of manually-entered notes.

Step six — verify before you celebrate. Re-run your baseline duplicate queries. Build a filtered list or report showing records created today, and eyeball a sample. Open the error file. Check total record counts against expected counts, not against "looks about right."

How to import contacts and deals from a CSV file into HubSpot CRM without creating duplicates in 2027 — figure 7

Sequencing note that matters more than it sounds: import contacts and companies *before* deals when you're doing it in separate passes. Deals associate to contacts and companies; if the parent records don't exist yet, the associations silently fail and you get orphaned deals nobody can find in a contact's timeline. If you use the multi-file import, HubSpot handles ordering for you — that's most of its value.

Adjacent workflows this same discipline fixes

The unique-key discipline generalizes well beyond CSV imports, and once a team internalizes it, several neighboring problems get easier.

Form submissions and list uploads. Marketing uploads a conference list; sales complains about duplicate contacts. Almost always this is fine — HubSpot dedupes contacts on email — and the real issue is that the same human appears under a personal Gmail and a work address. No importer can solve that; it's a data-governance question about whether you treat email as identity. Some teams add a secondary key like normalized full name + company domain and run a periodic reconciliation report rather than trying to enforce it at import time.

Two-way CRM sync. If HubSpot is syncing bidirectionally with another system, an import can trigger an echo: you import 500 deals, the sync pushes them to the other system, the other system pushes them back with new IDs, and now you have 1,000. Before a large import, check whether an active sync will see the new records and how it identifies matches. Pausing a sync for the duration of an import, then resuming it after verification, is standard practice and costs nothing.

How to import contacts and deals from a CSV file into HubSpot CRM without creating duplicates in 2027 — figure 8

Line items and products. Deals often carry line items, and line items have the same weakness deals do — no natural unique key. If you import line items separately, you can duplicate them onto deals that already have them. The same custom-unique-property trick applies.

Data-warehouse-first architecture. The most durable pattern for orgs past a certain size is to stop importing into HubSpot from files at all. Land raw data in a warehouse, model it there with a proper primary key, and use reverse ETL to push it into HubSpot keyed on that primary key. Duplicates become structurally impossible because the key is enforced upstream. The cost is warehouse infrastructure and a modeling layer, which is why this is a size-dependent answer rather than a universal one.

Enrichment and third-party software. Enrichment tools that write into HubSpot are another duplicate vector, especially ones that create records for newly discovered contacts. Any software with create permissions on your CRM should be audited for what key it matches on. Two enrichment vendors both creating contacts on slightly different matching rules will manufacture duplicates faster than any human import ever could.

How to import contacts and deals from a CSV file into HubSpot CRM without creating duplicates in 2027 — figure 9

Custom objects. If you've built custom objects, they inherit the deal problem exactly: Record ID is the only native unique key, and you should define a custom unique property before the first import rather than after the first mess. The pattern is identical.

What tends to go wrong, and the tells

"HubSpot created duplicate contacts even though email was mapped." Nearly always one of: the email column wasn't actually mapped to the Email property (it was mapped to a custom "Work Email" text field), or the rows had empty emails. A row with no email has nothing to match on, so HubSpot creates a new contact every time. Filter blank emails out before importing and handle them separately.

"The deals imported twice." The key column was missing, wasn't marked unique, or wasn't populated for every row. A blank unique-value property doesn't block anything — blanks are not considered duplicates of each other.

"Associations didn't stick." Either the linking column values don't match exactly between files (whitespace, casing on a non-email field), or the parent records didn't exist yet.

How to import contacts and deals from a CSV file into HubSpot CRM without creating duplicates in 2027 — figure 10

"Everything imported but half the fields are blank." Usually a mapping problem: dropdown properties only accept values that already exist as options, and a value not in the list gets dropped rather than created.

"It worked in the test and failed at scale." File size, timeouts, and rate limits are real. Chunk the file.

The general tell that separates a controlled import from a hopeful one: before you upload, can you state in one sentence what makes each row unique and what HubSpot will do when it finds a match? If you can't, you're not importing — you're gambling.

Related questions

Does HubSpot merge duplicate deals automatically?

No. HubSpot's automatic deduplication and its "Manage duplicates" tool cover contacts and companies, matching on email, domain, and similarity scoring. Deals have no equivalent automatic dedupe. Prevention through a unique key is the only reliable approach.

Can I undo a HubSpot import?

Recently completed imports can be rolled back from the imports screen, which deletes the records that import created. There is a time window on this, and it won't reverse updates to pre-existing records — only creations. Don't rely on it as your safety net.

What is the strongest match key for a HubSpot import?

Record ID. It's HubSpot's internal object identifier, exact, immutable, and never reused. Export it, join it into your source file, and map it. Any import carrying valid Record IDs updates rather than creates, for every object type.

Should contacts or deals be imported first?

Contacts and companies first, deals after — deals associate upward to those records. Or use HubSpot's multi-file import with associations, which handles the ordering internally and links records in a single run.

How many rows can one HubSpot import handle?

Up to 1,048,576 rows and 512 MB per file, with up to 10 files in a multi-file import. Practically, chunk into 20,000–50,000 row batches so a failure costs one chunk rather than the whole migration.

FAQ

Which properties does HubSpot treat as unique identifiers by default?

Record ID for every object, plus Email for contacts and Domain Name for companies. Those are the fields the importer uses to decide "update" versus "create." Deals, line items, tickets, and custom objects have only Record ID by default, which is why you have to supply your own key when importing them from a source system that has never touched HubSpot.

How do I create a custom unique property for deals?

In Settings → Properties, create a single-line text property on the Deal object and enable the option requiring unique values. HubSpot enforces uniqueness at the platform level from that point forward — an attempt to create a second record with the same value is rejected. There's a limit on how many unique-value properties each object can have, so choose the key carefully rather than creating several.

Will importing overwrite my existing data?

If a row matches an existing record, mapped properties are updated with the file's values. Whether blank cells wipe existing values depends on the import setting you choose, so read that option rather than clicking through it. Unmapped properties are untouched. The safest habit is exporting the affected records first, so you have a restore path.

Can I import contacts and deals in one file?

HubSpot's multi-file import expects separate files per object, linked by a common column, and accepts up to 10 files per import. A single-file import creating both objects at once is supported for some object combinations, but the multi-file path is clearer to reason about and easier to debug when something goes wrong.

Does using Zapier or similar software prevent duplicates?

Only if you configure it to. Most connectors default to "create record," which duplicates freely. You need a search step that looks for an existing record on your key first, then branches to update or create. That search-before-write pattern is what any middleware has to implement — the tool doesn't do it for you by default.

What should I do if duplicates already exist?

For contacts and companies, use HubSpot's duplicate management tool to review and merge suggested pairs, and be aware merging is not fully reversible. For deals, you'll have to identify duplicates yourself with a filtered list or an export, decide which record is authoritative, move associations and notes over, and delete the rest. Then fix the key so it stops happening.

Sources

flowchart TD S["How to import contacts and deals from "] S --> N0["Two paths: HubSpot's native CSV import"] N0 --> N1["How to decide between them"] N1 --> N2["The concrete numbers behind each optio"] N2 --> N3["Implementation: the sequence that actu"]
flowchart LR C["How to import contacts and deals from "] C --> H0["The concrete numbers behind each optio"] C --> H1["Implementation: the sequence that actu"] C --> H2["Adjacent workflows this same disciplin"] C --> H3["What tends to go wrong, and the tells"]

Related on PULSE

Download:
Was this helpful?  
⌬ Apply this in PULSE
Free CRM · Revenue IntelligenceAudit pipeline, score reps, ship the fixHow-To · SaaS ChurnSilent revenue killer playbook