Skip to content
hubreven
CRM Data5 min read

How to import contacts into HubSpot without creating duplicates

HubSpot matches imported contacts on email address, and companies on domain. Rows without those values create new records every time the file is imported. To avoid duplicates, profile the file first, deduplicate before upload, and include a unique external ID column so repeat imports update rather than create.

By HubReven

The import runs, the counts look plausible, and three weeks later your database has 12,000 contacts where it should have 8,000.

Here is what HubSpot is doing during an import and how to make a second run safe.

What HubSpot matches on

Contacts match on email address. If the email exists, the record updates. If it does not, a new contact is created.

Companies match on domain.

Deals, tickets and custom objects have no natural key at all. Import the same deal file twice and you have every deal twice.

Two consequences follow immediately.

Rows without an email address always create a new contact, every single time, no matter how many times you import them. A file where 30% of rows have no email will grow your database by 30% of its size on every run.

And formatting differences count as different values. John@Acme.com with a trailing space is not the same string as john@acme.com unless you normalise it first.

Add a unique external ID, always

The single most useful thing you can do, and the step almost everyone skips.

Create a contact property called something like source_system_id, set it to unique, and include that column in the file. Then select it as the matching property during import.

Now the import keys on your ID rather than on email. A person who changes email address still matches. A repeat import updates instead of creating. And you can re-run the same file safely, which you will need to do, because the first import is never the last one.

This is the same principle that makes an integration replay safe, for exactly the same reason: every write should be an upsert on a stable key.

Profile the file before you upload it

Twenty minutes in a spreadsheet saves a week of cleanup. Five checks.

Duplicate rate. Count unique emails against total rows. Above 5% means dedupe before uploading, because merging inside HubSpot afterwards is slow and partly manual.

Missing emails. Count rows with no email. Decide now: import them and accept they will never match, or hold them back.

Format consistency. Dates in one format, not three. Phone numbers with a consistent country prefix. Country names or ISO codes, not both. Currency as a number, without symbols.

Field lengths and encoding. Check for text longer than the property allows, and open the file as UTF-8 to catch mangled accented characters before they are permanent.

Association keys. If contacts link to companies, confirm every company reference actually exists in the company file or in the portal. Orphans import silently and you find them when a report is wrong.

Import order

Order matters because associations need both sides present.

  1. Companies first.
  2. Contacts second, with the company domain or ID column for association.
  3. Deals third, referencing contacts and companies.
  4. Activities and notes last.

Doing contacts first and companies second produces contacts with no company, and fixing it means re-importing anyway.

Test with 20 rows

Never import the full file first.

Take 20 rows that cover your edge cases: one with a missing email, one with an accented name, one with a long text field, one that should match an existing record and one that should create. Import those, open each record, and check every field landed where you expected.

Twenty rows takes ten minutes and catches almost everything. A 40,000 row mistake takes days to unwind.

After the import

Check the error file. HubSpot produces one for rejected rows. Read it, do not archive it.

Reconcile the counts. Rows in the file, records created, records updated, rows rejected. They should add up. If they do not, find out why before anyone starts working in the portal.

Tag the batch. Put every imported record on a static list named for the import. If something is wrong, that list is how you find them again, and it is exactly what static lists are for.

When an import is not the right tool

If this is a one time load of clean data, import is fine.

If it is a recurring load from another system, stop building a habit of manual imports and build a pipeline instead. Same keyed upserts, running on a schedule, with a quarantine report for rows that fail rather than a person reconciling a spreadsheet every Monday.

And if it is nine years of history with associations and activity timelines, that is a migration with a reconciliation step, not an import. The difference is whether anyone signs off that both systems agree.

Frequently asked questions

How does HubSpot decide if an imported contact is a duplicate?

By email address for contacts and domain for companies. If you include a unique external ID property and select it as the matching property, HubSpot keys on that instead, which is more reliable.

Why did my import create duplicates?

Almost always rows with no email address, which always create new records, or formatting differences such as trailing spaces and capitalisation that make two identical addresses look different to the matcher.

Can I undo a HubSpot import?

There is a rollback option available for a limited window after an import, but it is not something to rely on. Tag every import to a static list so you can always find and act on the batch.

Should I import contacts or companies first?

Companies first, then contacts with the company reference, then deals, then activities. Associations need both sides to exist already.

Get the next one

One email a month. Unsubscribe anytime.