HubSpot Import Contacts from CSV: Step-by-Step Guide (2026)
Import contacts to HubSpot from CSV files. Covers Quick Import, Advanced Import, API methods, deduplication, and troubleshooting common errors.

HubSpot Import Contacts from CSV: Step-by-Step Guide (2026)
You can import contacts to HubSpot from a CSV file using the built-in import tool under Data Management > Data Integration, or by clicking Import on the Contacts index page. HubSpot requires at least one of three fields -- First name, Last name, or Email -- and supports files up to 512 MB on paid plans.
That is the short answer. The longer answer involves four different import methods, tier-specific limits, deduplication quirks, and a handful of errors that reject your rows without much explanation. HubSpot scatters this information across five separate knowledge base articles. I pulled it all together here so you do not have to tab between them.
We will cover: preparing your CSV, Quick Import for simple lists, Advanced Import with full mapping control, multi-object imports with company associations, API imports for automation, duplicate handling, and a troubleshooting reference for every common error I have run into.
Preparing Your CSV File
Get the file right and the import is boring in the best way. Get it wrong and you will spend more time fixing errors than you saved by not entering contacts manually. Ask me how I know.
File Format Requirements
| Requirement | Details |
|---|---|
| File types | .csv, .xlsx, or .xls |
| Sheets | One sheet only (multi-sheet files will be rejected) |
| Header row | Required. Each column header must correspond to a HubSpot property |
| Max columns | Less than 1,000 |
| Encoding | UTF-8 required if your data includes non-English characters |
Required Columns for Contacts
HubSpot needs at least one of these three fields per row:
- Email (strongly recommended -- this is how HubSpot deduplicates)
- First name
- Last name
You can technically import with just a First name column. It works. But if you skip Email, every single row creates a brand new contact. No deduplication. No matching. You end up with a mess of duplicate records. Include Email. Always.
Import Limits by HubSpot Plan
Bookmark this table. The limits apply to a rolling 24-hour window -- they do not reset at midnight, which catches people off guard.
| Limit | Free | Starter / Professional / Enterprise |
|---|---|---|
| File size | 20 MB | 512 MB |
| Imports per day | 50 | 500 |
| Rows per day | 500,000 | 10,000,000 |
| Rows per file | 500,000 | 1,048,576 |
| API rows per day | N/A | 80,000,000 |
If your file exceeds the rows-per-file limit on the Free plan, HubSpot will process it over multiple days. On paid plans, you hit the Excel row limit of roughly one million rows per file.
Property Value Formatting
HubSpot is picky about formatting. Get these wrong and the values silently import as blank -- no error, just empty fields:
| Field Type | Expected Format |
|---|---|
| Date | Day/month/year, month/day/year, or year/month/day. Separators: /, -, or . |
| Date and time | Add timestamp as hh:mm or UNIX timestamp in milliseconds |
| Dropdown/Select | Must match the label or internal value exactly |
| Multiple checkboxes | Semicolon-separated, no spaces: value1;value2 |
| Phone number | +[country code][number] ext[number] (e.g., +11234567890 ext123) |
| Single checkbox | True/Yes or False/No |
| Contact owner | User name, email address, or internal Owner property value |
| Additional emails | Semicolon-separated in an "Additional email addresses" column |
Pre-Import Checklist
Before you upload anything:
- Remove duplicate emails within your file. If two rows share the same email, you may get errors or unintended overwrites.
- Validate email format. HubSpot rejects any email that does not follow
name@domain.comformat. - Match dropdown values exactly. If your HubSpot "Lead Status" property has "Open" as an option, importing "open" (lowercase) will fail silently -- the field imports as blank.
- Standardize date formats. Pick one format and stick with it across the entire column.
- Check your row count. Free plan? Stay under 500,000 rows per day. Paid plan? Under 10 million.
Method 1: Quick Import (Contacts Only)
Quick Import is the fastest path when you have a plain CSV of contacts and nothing else. No company associations, no deal linkages. Just contacts going in.
When to Use Quick Import
- You are importing contacts only (no companies, deals, or tickets)
- You do not need association labels
- You want the fewest possible steps
Step-by-Step
- Navigate to Contacts in HubSpot
- Click the Import button in the upper right
- Select Quick import
- Drag and drop your CSV file or click to browse
- HubSpot automatically maps columns to properties based on header names
- Review the mapping. Fix anything it got wrong.
- Click Finish import
Quick Import skips a lot of options. You cannot set marketing contact status, configure GDPR legal basis, or choose between create-only and update-only modes. It defaults to creating new contacts and updating existing ones based on email matching.
Honestly, for one-off imports under a few thousand contacts, Quick Import is all you need. Once you want more control, move to Method 2.
Method 2: Advanced Import via HubSpot UI
Advanced Import is what you actually want for production imports, migrations, or any situation where you need to control what gets created versus updated. More steps, but worth it.
Step-by-Step Walkthrough
- Go to Data Management > Data Integration (or click Import on the Contacts page)
- Click Import data in the "Import a file" section
- Click Advanced imports (all objects)
- Select Contacts as the object type, then click Next
- Choose your import mode:
- Create and update contacts -- Creates new records, updates existing ones (default)
- Create new contacts only -- Skips any row that matches an existing contact
- Update existing contacts only -- Skips any row that does not match an existing contact
- Click choose a file and select your CSV
- If your column headers are in a language other than your portal default, select the correct language
- Click Next
Column Mapping
HubSpot tries to auto-map your CSV headers to properties. It does a decent job when your headers match property names exactly (e.g., "First Name" maps to firstname). When it guesses wrong, you pick the correct property from a dropdown. Not hard, just tedious if you have 30+ columns.
Here is the step people miss: make sure Email has the key icon next to it. That key icon means HubSpot is using it as the unique identifier for deduplication. Without it, HubSpot cannot match rows to existing contacts. I have seen entire imports create thousands of duplicates because someone skipped this.
If you want to update existing records by Record ID instead of Email, include a "Record ID" column and set that as the unique identifier. Record ID supersedes all other identifiers.
Optional Settings
After mapping, you get several configuration options:
- Name your import -- Use something descriptive like "Q1 2026 Webinar Attendees" rather than "contacts_final_v2"
- Consent checkbox -- You must confirm these contacts expect to hear from you. This is not optional. HubSpot will not let you import purchased lists.
- Marketing contacts -- Toggle on to set imported contacts as marketing contacts (requires Marketing Hub Starter or higher)
- Breeze Intelligence enrichment -- Auto-enrich records with additional data (requires Breeze credits)
- Create a contacts segment -- Automatically creates a static list from the imported contacts
- GDPR legal basis -- Set the legal basis for processing contact data
- Date and number format -- Configure how HubSpot interprets dates and numbers in your file
- Time zone -- Set the time zone for date/time properties
Click Finish import and wait. Small files (under 10,000 rows) finish in under a minute. Larger files can take several minutes. There is no progress bar that actually tells you how far along it is -- you just wait.
The "Don't Overwrite" Option
During mapping, you can select Don't overwrite for individual properties. When enabled:
- New records get the imported value
- Existing records that have never had a value for that property get the imported value
- Existing records that have or ever had a value are not updated
This is great for filling in gaps without clobbering data your sales team already entered. One gotcha though: "ever had a value" includes properties that were set and then manually cleared. Even if the field is blank right now, if it ever held a value, the import will not touch it. That behavior is confusing the first time you hit it.
Method 3: Multi-Object Import (Contacts + Companies)
When your contacts have company data attached, you can import both at once. HubSpot creates the associations automatically, which saves you a second pass.
When to Use Multi-Object Import
- Importing contacts along with their company associations
- Migrating from another CRM that exports contacts and companies together
- Setting up accounts and contacts simultaneously
How It Works
You have two approaches:
Single file: Include both contact and company columns in one CSV. You will need a common column (like Company Domain Name) that HubSpot uses to associate the contact with the company.
Multiple files: Upload separate CSV files for contacts and companies, each with a shared identifier column. This is cleaner when your data structures are complex.
During the import wizard, select both Contacts and Companies as object types. HubSpot will ask you to identify which columns belong to which object and which column serves as the association key.
Association Labels
On Professional and Enterprise plans, you can assign association labels during import. These labels describe the relationship -- for example, marking a contact as "Decision Maker" for their associated company.
Free and Starter plans can create associations but cannot assign labels. The link exists, just without the descriptive tag. Annoying if you need it, but livable.
Method 4: HubSpot API Import
For recurring imports, automated pipelines, or anything above 10 million rows per day, you need the API. The UI will not cut it at that scale.
API Details
| Property | Value |
|---|---|
| Endpoint | POST /crm/v3/imports |
| Content type | multipart/form-data |
| Authentication | OAuth or Bearer token |
| Required scope | crm.import |
| Max rows per file | 1,048,576 (or 512 MB, whichever comes first) |
| Max rows per day | 80,000,000 |
| Max concurrent imports | 3 (additional imports are queued as DEFERRED) |
Sample cURL Request
curl -X POST https://api.hubapi.com/crm/v3/imports \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-F "importRequest={
\"name\": \"January 2026 Contacts\",
\"importOperations\": {
\"0-1\": \"UPSERT\"
},
\"dateFormat\": \"MONTH_DAY_YEAR\",
\"files\": [
{
\"fileName\": \"contacts.csv\",
\"fileFormat\": \"CSV\",
\"fileImportPage\": {
\"hasHeader\": true,
\"columnMappings\": [
{
\"columnObjectTypeId\": \"0-1\",
\"columnName\": \"Email\",
\"propertyName\": \"email\",
\"columnType\": \"HUBSPOT_ALTERNATE_ID\"
},
{
\"columnObjectTypeId\": \"0-1\",
\"columnName\": \"First Name\",
\"propertyName\": \"firstname\"
},
{
\"columnObjectTypeId\": \"0-1\",
\"columnName\": \"Last Name\",
\"propertyName\": \"lastname\"
}
]
}
}
]
};type=application/json" \
-F "files=@contacts.csv"A few things worth calling out: "0-1" is the objectTypeId for contacts (not obvious from the docs). The importOperations field accepts UPSERT (create or update), CREATE, or UPDATE. Set the Email column's columnType to HUBSPOT_ALTERNATE_ID so HubSpot uses it for deduplication -- skip this and you will get duplicates.
Import States
After submitting, poll the import status via GET /crm/v3/imports/{importId}:
| State | Meaning |
|---|---|
| STARTED | Recognized but not yet processing |
| PROCESSING | Actively importing rows |
| DONE | Complete |
| FAILED | Error occurred -- check error details |
| CANCELED | User cancelled the import |
| DEFERRED | Queued because 3 imports are already running |
If you hit DEFERRED status, just wait. HubSpot processes queued imports automatically once a slot opens up. Do not resubmit. Seriously. You will just pile more into the queue and make it worse.
How HubSpot Handles Duplicates
Deduplication is where people get burned. Here is exactly how HubSpot decides whether to create a new contact or update an existing one -- and the behavior is not always intuitive.
Email-Based Deduplication
HubSpot uses the Email property as the default unique identifier for contacts. This is automatic and cannot be turned off.
With an Email column in your CSV:
- If a contact already exists with the same email address, HubSpot updates the existing record with the imported data
- If no match exists, HubSpot creates a new contact
Without an Email column:
- Every row creates a new contact record. No deduplication at all. This is the number one cause of accidental duplicate contacts and you will probably not notice until your sales team complains.
Secondary Email Behavior
This one is weird. If you use a contact's secondary email as the unique identifier:
- Without Record ID: The secondary email does NOT replace the primary email
- With Record ID included: The secondary email WILL replace the primary email
If multiple contacts already exist with the same email address in your HubSpot database, the import will throw an error for that row and skip it entirely. You need to resolve the existing duplicates first.
Blank Cells Do NOT Clear Values
This catches everyone at least once. If your CSV has a blank cell for a property that already has a value on the existing contact, HubSpot ignores the blank cell. The existing value stays. You cannot use imports to bulk-clear property values. Frustrating, but that is how it works.
To clear values in bulk, use the manual bulk edit feature or create a workflow with an "Edit records" action.
Custom Unique Properties
Beyond Email, you can create up to 10 custom unique identifier properties per object. But even with a custom unique property, the Email column still requires unique values if you include it. There is no way around that constraint. I have tried.
Troubleshooting Common Import Errors
After an import completes, HubSpot generates an error file you can download. Always download it. Here are the errors you will probably hit and how to fix them.
Error Reference Table
| Error | What Went Wrong | Fix |
|---|---|---|
| Failed validation of Email | Email does not follow name@domain.com format | Check for spaces, missing @ signs, or invalid domains |
| Duplicate alternate ID | Same email appears multiple times in your file | Deduplicate your CSV before uploading |
| Invalid enumeration option | Dropdown value does not match any option in HubSpot | Check the exact option labels in your HubSpot property settings |
| Could not find owner | Owner name or email does not match a HubSpot user | Verify the user exists and the email matches exactly |
| Could not parse date | Date format does not match the format you selected during import | Standardize all dates to the format you chose (e.g., MM/DD/YYYY) |
| Could not parse number | Non-numeric characters in a number field | Remove currency symbols, commas, or text from number columns |
| Missing required property | A required field has no value in that row | Add the missing value in your CSV |
| GDPR blocklisted email | This email was permanently deleted under data privacy rules | The contact must re-submit through a form. You cannot re-import them. |
| Limit exceeded | You hit your plan's record storage limit | Delete unneeded contacts or upgrade your plan |
| Row data too large | A single cell or row exceeds 1 MB | Trim the data. Notes fields are usually the culprit. |
| Incorrect number of columns | A column exists without a header | Add headers to all columns or remove the extra columns |
Fixing Errors During Import
HubSpot now lets you fix some errors during the mapping stage without re-uploading your file:
- Edit errored values directly in the import wizard
- Replace a value across all matching rows at once
- Choose "Don't import this value" to skip specific cells
This inline editing only shows the first 1,000 rows, but replacements apply to all rows in the file. For systematic errors like a wrong date format, this saves you from re-uploading. Nice feature, honestly.
Best Practices for Clean Imports
I have not tested every edge case across every HubSpot plan tier, but after running a lot of CSV imports, here is what actually matters:
Before the import:
- Validate email format programmatically. A quick regex pass catches 90% of email errors before HubSpot even sees the file.
- Match every dropdown and select value to the exact labels in HubSpot. Case matters. "Open" and "open" are different.
- Remove rows with duplicate email addresses within your file.
- Strip trailing whitespace from cells. Invisible spaces cause matching failures and they are maddening to debug.
- Test with a 10-row sample before importing your full dataset. Every time.
During the import:
- Always include the Email column. Always.
- Use "Create and update" mode unless you have a specific reason for create-only or update-only.
- Name your imports descriptively. You will thank yourself when reviewing import history six months later.
After the import:
- Download the error file immediately. Review it before moving on.
- Spot-check 5-10 records in HubSpot to confirm data mapped correctly.
- Check the "Contacts" list count to verify the expected number of records were created or updated.
When the Built-In Importer Is Not Enough
HubSpot's import tool works well enough for periodic, manual imports. But it has real limits. You cannot schedule recurring imports. The UI does not support data transformation during import. And if you are building a product where your customers need to import their own data, pointing them at HubSpot's import wizard is a bad experience.
If you are building a SaaS application and need to let your users import CSV data into your system, ImportCSV gives you an embeddable CSV importer that handles validation, mapping, and error correction -- the same problems HubSpot's importer solves, but as a component you can drop into your own product.
For everyone else: HubSpot's built-in tools cover most contact import scenarios. Pick the method that matches your scale -- Quick Import for small batches, Advanced Import for full control, the API for automation. That is it. No need to overthink it.
Wrap-up
CSV imports shouldn't slow you down. ImportCSV aims to expand into your workflow — whether you're building data import flows, handling customer uploads, or processing large datasets.
If that sounds like the kind of tooling you want to use, try ImportCSV .