Why Does Intercom's CSV Import Drop Rows on Large Contact Lists?
Upload an 8,000-row CSV to Intercom and watch the contact count only climb by three or four thousand, and there is no error to explain the gap. That's because Intercom isn't rejecting the missing rows. Before it creates a contact, it checks whether the row already matches someone in your workspace, first by Intercom's internal ID, then by user_id, then by email. Any match becomes an update to the existing record instead of a new one. Your file didn't lose rows. Most of them merged.
Intercom lays this matching order out in its own import documentation: "if both are present, user_id takes priority" over email, and a row needs at least one of the two to import at all. The gap people report isn't a bug so much as the intended behavior of an update-in-place importer running against a list that overlaps more with existing contacts than anyone expected.
How Intercom decides a row already exists
The matching hierarchy matters because each level fails differently:
- Intercom ID only applies if you exported the list from Intercom itself, so it rarely shows up on a purchased or merged list.
user_idneeds an exact match. If your CSV supplies auser_idthat doesn't match an existing one, Intercom won't fall back to checking the email on that same row, it just creates a new contact under the newuser_id, which is how imports create duplicates instead of preventing them.- Email is the fallback nearly every CSV import ends up using, since most purchased or exported lists don't carry Intercom's own identifiers.
A support thread on Intercom's community forum describes exactly this: a workspace imported roughly 8,000 leads and ended with about 3,700 new records, no error message anywhere in the flow. An Intercom support engineer's answer was to check whether the import was updating existing leads rather than creating them, and a member of Intercom's team confirmed a lead only needs an email to import, which is precisely what makes email-based matching so aggressive on a list that already overlaps your workspace.
Nadia's 8,200-row list
Brightlane, a scheduling-software company, had just closed a deal to absorb a smaller competitor's customer base. Nadia Kessler, who runs lifecycle marketing there, had to get those users into Intercom before the migration emails went out. She exported the acquired company's user list, 8,200 rows, cleaned up the column headers to match Intercom's import format, and uploaded the file expecting roughly 8,200 new contacts to message about the migration.
The import finished showing 3,180 new contacts created.
Nadia, in the #lifecycle Slack channel: Just imported the acquired-company list and Intercom says 3,180 added. The file has 8,200 rows. Did something time out?
Teammate: Did any of those users already sign up for a Brightlane trial on their own? A lot of scheduling tools get evaluated in parallel.
Nadia: ...yeah, actually. We ran a free trial promo at the same conference where they were shopping around. That would explain a chunk of it.
The overlap wasn't an import failure. Around 5,000 people on the acquired company's list had already created a Brightlane trial account under the same email address during the promo, so Intercom matched those rows and updated the existing contacts' attributes instead of adding new ones. The acquisition data was there, just folded into records Nadia already had, not sitting in a pile of failed rows waiting to be retried.
The checklist that catches this before you upload
Once you know matching happens by email, most of the confusion is avoidable:
- Dedupe your source list against Intercom first, not just against itself. Export your existing contact emails and diff them against the import file before uploading, so the "new contacts" number you expect is grounded in reality.
- Pick one identifier and use it consistently. Mixing rows that carry
user_idwith rows that only carry email, in the same file, is what Intercom's own docs warn creates duplicate contacts rather than clean matches, since auser_idthat doesn't match anything skips the email fallback entirely. - Check the file size before anything else. Intercom's import documentation puts the ceiling at 20MB per file; anything larger needs to be split into batches, and a failed upload from file size looks nothing like a row-count mismatch, so it's worth ruling out first.
- Confirm every row has an email. Intercom's docs state plainly that "all users or leads in your CSV must have an email address," and rows missing one won't import regardless of what else they contain.
None of this recovers rows that already merged. It just means the next import doesn't surprise you the same way.
What even a clean import can't carry
There's a second limit worth knowing before you plan around CSV imports: Intercom's own documentation says company attributes and company-level data can't come in through a CSV contact import at all. You can bring in people, but the account they belong to, its plan, its revenue tier, whatever context would let you message by company rather than by individual, has to be built separately, by hand or through Intercom's API. A perfect import with zero merged rows still hands you a flat list of people with no organizational shape.
Where re-uploading the file stops being the fix
A CSV import is a snapshot, accurate the moment you export it and stale the moment anyone's status changes afterward. For a one-time backfill, matching quirks and missing company data are annoyances you work around once. They become a real problem when contact lists need to stay current, when an acquired customer base keeps evolving, or when the same duplicate-creation risk resurfaces every time someone runs the import again for a fresh batch of leads.
That's the gap we built Modem to close. Instead of a periodic file drop, Modem reads Intercom conversations as they happen, along with Slack, GitHub, and your other tools, and builds the person and company graph from that live activity. A contact who first shows up in a support conversation gets attached to their company automatically, the thing CSV import can't do for you even when it works perfectly. If the acquired list Nadia imported had instead flowed in as conversations happened, the 5,000 overlapping trial users would have shown up already linked to their company, no dedupe spreadsheet required. Modem is the product we sell, so read that comparison with our bias in mind. Tightening your CSV process instead is covered in how to build a customer context graph. For the Intercom side specifically, see how to track feature requests in Intercom.
Before you upload the next list
Before your next large import, export your current Intercom contact emails, diff them against the file you're about to upload, and note how many overlap. That number is roughly how many "missing" rows to expect, and it turns a confusing post-import surprise into a number you already knew was coming.
