Import contacts from a CSV
Upload a CSV, match its columns to contact fields, and watch the import run.
Go to Contacts, click Import CSV, choose your file and (optionally) a list, then map each column to a contact field and click Start import. The import runs in the background and the page updates as it goes; you can close the tab and come back.
Your file needs a header row and must be UTF-8 CSV, up to 25MB.
Import a file
- From Contacts, click Import CSV. (From a list’s page, Import contacts does the same with that list pre-selected.)
- Choose your CSV file.
- Pick a list under Add to list (optional). Leave it as No list if you only want the contacts on your account, but contacts on no list can’t be sent to until you add them to one.
- Click Upload & map columns.
- On the Map columns screen, set each column to a contact field. Common headers (email, first name, last name) are matched for you. Anything you don’t want stays at — skip —.
- Click Start import.

Mapping rules
- Exactly one column must map to
email_address. Map none or two and the import won’t start; your mapping is kept so you can fix just that row. - Built-in targets are
email_address,first_name,last_name,sourceandstatus. Any custom field appears as custom:key. statusis never mapped for you. Map it only if you deliberately want the file to carry opt-out state: see below.- Re-importing a narrower file won’t blank names or custom fields already on a contact; it merges.
What happens to each row
While the import runs it also cleans the file, and the results card breaks the outcome down:
- Created / Updated: new contacts, and existing contacts whose details were refreshed.
- Skipped (not imported): rows that never became a contact: an address that isn’t a valid email, and blank rows.
- Imported as cleaned (kept off the list): the contact is created so a repeat import recognises it, but it’s marked
cleanedand left off your list. Disposable addresses, domains with no mail server, and addresses already on your suppression list land here. - Flagged (imported): imported normally, but worth a look. Role addresses (
info@,sales@) are the usual case. - Auto-corrected: obvious typos in well-known consumer domains are fixed for you (
gmial.com→gmail.com). Expand Show N auto-corrected typos to see every before-and-after pair.
If any rows were rejected outright, N error rows lists them with a reason, and Download CSV gives you the whole set to fix and re-upload.
Imports don’t start automations. Someone added to a list by an import doesn’t enrol in an automation that triggers on joining that list. See Why imports don’t trigger automations.
If a status column is mapped
Mapping a status column is how you carry opt-outs across from another provider. A row marked unsubscribed lands as an unsubscribed contact with a suppression behind it, so a later re-import can’t quietly resurrect them. A row marked cleaned lands as a cleaned contact, kept off the list.
An imported status is treated as a hint about what the sender knew, never as bounce evidence. It can’t create a bounce or complaint suppression, and it can’t strengthen a suppression that’s already there.
When an import doesn’t finish
- “This import didn’t finish.” Something went wrong partway through. Retry import picks up from where it stopped.
- “We couldn’t read the column headers from this file.” Usually an Excel file renamed
.csv. Re-save it as CSV UTF-8 and upload again. - “This import couldn’t be processed, and sending is paused on your account.” The file didn’t meet our import quality bar. See This list doesn’t meet our import quality bar.
Existing imports are listed under Past imports, with their counts and results card kept.