> ## Documentation Index
> Fetch the complete documentation index at: https://docs.brudcast.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Import and export contacts

> Upload a spreadsheet, map its columns and fix the rows that failed, then export your contacts back out as a CSV.

export const DemoVideo = ({id, title, embedUrl, src, poster, duration}) => {
  if (embedUrl) {
    return <figure className="brd-media" data-media-id={id}>
        <iframe className="brd-media-frame w-full aspect-video" src={embedUrl} title={title} allow="accelerometer; autoplay; clipboard-write; encrypted-media; picture-in-picture" allowFullScreen />
      </figure>;
  }
  if (src) {
    return <figure className="brd-media" data-media-id={id}>
        <video className="brd-media-frame w-full aspect-video" src={src} poster={poster} controls playsInline preload="metadata" />
      </figure>;
  }
  const label = duration ? `Video walkthrough coming soon · ${duration}` : "Video walkthrough coming soon";
  return <Placeholder id={id} kind="video" label={label} description={title} ratio="16 / 9" icon={<PlayIcon />} />;
};

export const Loop = ({id, src, alt, caption}) => {
  if (!src) {
    return <Placeholder id={id} kind="loop" label="Animation coming soon" description={alt} icon={<PlayIcon />} />;
  }
  return <figure className="brd-media" data-media-id={id}>
      <video className="brd-media-frame" src={src} autoPlay muted loop playsInline aria-label={alt} />
      {caption && <figcaption className="brd-media-caption">{caption}</figcaption>}
    </figure>;
};

export const Screenshot = ({id, src, srcDark, alt, caption}) => {
  if (!src) {
    return <Placeholder id={id} kind="screenshot" label="Screenshot coming soon" description={alt} icon={<ImageIcon />} />;
  }
  return <figure className="brd-media" data-media-id={id}>
      <img className="brd-media-frame block dark:hidden" src={src} alt={alt} />
      <img className="brd-media-frame hidden dark:block" src={srcDark || src} alt={alt} />
      {caption && <figcaption className="brd-media-caption">{caption}</figcaption>}
    </figure>;
};

Bring an existing audience into Brudcast from a CSV, and take your contacts back out again whenever
you need them. On the way in, you map your file's columns and review the counts before anything is
written.

<Screenshot id="ss-contacts-importing-hero" alt="Import history showing a completed import with 4,812 contacts imported, 12 errors and an Errors download button" />

<Info>
  **Before you start:** you need a CSV file of up to 10 MB with an email address on every row, and
  permission to contact everyone in it. New contacts count toward your plan's contact limit.

  **Names and phone numbers don't come in this way.** A dashboard import doesn't save the
  **First Name**, **Last Name** or **Phone Number** columns, even though the mapping step lets you
  pick them, and custom field values can't be imported at all. If your file's names matter, import
  through the [API](/api-reference/introduction) instead, which saves first and last names mapped to
  `first_name` and `last_name`. Otherwise, plan to add names and phone numbers to the contacts
  afterwards.
</Info>

<Accordion title="Watch the walkthrough" icon="circle-play">
  <DemoVideo id="V07" title="Import contacts from a CSV" duration="2 min" />
</Accordion>

## Prepare your file

* Save it as a comma-separated `.csv` file in UTF-8.
* Put the column names in the first row, and one contact on each row after that.
* Give every row an email address. Rows without a valid one are skipped.
* Wrap a value that contains a comma in double quotes: `"Acme, Inc."`.
* Keep each contact on one line. Line breaks inside a cell aren't supported.
* To give a contact several tags, separate them with semicolons: `vip;early-adopter`.

For a template, select **Download the sample CSV** on the **Import** tab. It has the columns
Brudcast reads and two example rows.

### Columns that are imported

| Brudcast field | Example                   | Notes                                                  |
| -------------- | ------------------------- | ------------------------------------------------------ |
| **Email**      | `jane@example.com`        | Required. Identifies the contact and finds duplicates. |
| **Timezone**   | `Africa/Lagos`            |                                                        |
| **Language**   | `en`                      |                                                        |
| **Tags**       | `vip;newsletter`          | Added to the contact. An import never removes a tag.   |
| **Notes**      | `Met at the Lagos meetup` |                                                        |

## Import your file

<Steps>
  <Step title="Upload the file">
    Go to **Contacts > Import & Export** and stay on the **Import** tab. Drop your file on
    **Upload a CSV**, or click it to browse. The **Import Contacts** dialog opens on the
    **Map Columns** step once the file has uploaded.

    <Screenshot id="ss-contacts-importing-01-upload" alt="The Import tab with the Upload a CSV drop zone, the sample CSV tile and the migration tile" />
  </Step>

  <Step title="Map your columns">
    Each row of the dialog pairs a **Column in your file** with a **Brudcast field**. Common column
    names like "Email address" or "Tags" are matched for you. Change any pairing, or choose
    **Skip this column** to leave a column out. At least one column must be mapped, and one of them
    should be **Email**. **First Name**, **Last Name** and **Phone Number** are offered here, but a
    dashboard import doesn't save them.

    <Loop id="lp-contacts-importing-map" alt="Changing a column's Brudcast field from Skip this column to Tags" />

    Below the columns, two switches decide how the import behaves. Both are on by default:

    * **Allow partial upload**: skip rows with invalid data and import the rest. See
      [Partial uploads](#partial-uploads).
    * **Update existing contacts**: update contacts you already have. See
      [How duplicates are handled](#how-duplicates-are-handled).

    Select **Continue**.
  </Step>

  <Step title="Review the counts">
    The **Review** step checks the whole file without importing anything and shows how many rows
    will be **New contacts will be created**, how many match contacts you already have, and how
    many **Rows will be skipped due to errors**.

    <Screenshot id="ss-contacts-importing-02-review" alt="The Review step showing 4,700 new contacts, 112 existing contacts to update and 12 rows with errors" />

    If the new contacts wouldn't fit in your plan's remaining contact allowance, a warning says so
    here, before you start.
  </Step>

  <Step title="Add a list and tags (optional)">
    Turn on **Save your upload as a list** and enter a **List name** to put everyone in the file
    into a new list. Under **Add tags**, pick or create tags to apply to every imported contact.
  </Step>

  <Step title="Confirm consent and import">
    Tick **I have obtained explicit consent for communication from all contacts in this upload**.
    **Import** stays unavailable until you do. Then select **Import**.
  </Step>
</Steps>

## How duplicates are handled

A row is a duplicate when its email address matches a contact you already have. A repeat of an
address that appears earlier in the same file is also a duplicate, and isn't imported twice.

| **Update existing contacts** | What happens to a contact that already exists                                                                                                                                |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| On                           | The row's values overwrite the contact's. Blank cells leave the existing value alone, and tags are only ever added. If you saved the upload as a list, the contact joins it. |
| Off                          | The contact is left exactly as it is, and it isn't added to the new list.                                                                                                    |

Through the API you can also choose `create_new`, which creates a new contact for every row even
when the address already exists.

## Partial uploads

With **Allow partial upload** on, rows with a missing or invalid email address are skipped and
listed in the error report. Everything else is imported.

With it off, the import is all or nothing. If any row is invalid, or the new contacts wouldn't fit
in your contact limit, nothing is imported and the import is marked **Failed**.

## What happens next

The import runs in the background. **Import history** shows its progress while it runs, then its
totals:

| Column         | What it counts                                          |
| -------------- | ------------------------------------------------------- |
| **Total Rows** | Data rows in the file, not counting the header          |
| **Imported**   | New contacts plus rows that matched an existing contact |
| **Errors**     | Rows that were skipped                                  |
| **Duplicates** | Rows that matched an existing contact or an earlier row |

| Status         | Meaning                                          |
| -------------- | ------------------------------------------------ |
| **Pending**    | Waiting to start                                 |
| **Processing** | Rows are being written                           |
| **Completed**  | Finished. Some rows may still have been skipped. |
| **Failed**     | Nothing was imported, or the import stopped      |

When the import finishes, the notification bell shows **Contact import complete** or **Contact
import failed**, with a **View import** link back to this page.

A file you upload but never import is deleted after 24 hours.

## Download the error report

On a completed import with errors, select **Errors** on its row. You get a CSV with three columns:

| Column         | Contents                                                  |
| -------------- | --------------------------------------------------------- |
| `row`          | The row number in your file, counting the header as row 1 |
| `reason`       | Why the row was skipped                                   |
| `original_row` | The row as it appeared in your file                       |

| Reason                               | Fix                                                                                                                                   |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| `Missing email address`              | The row's email cell is empty, or no column is mapped to **Email**.                                                                   |
| `Invalid email format`               | The address isn't in the form `name@example.com`.                                                                                     |
| `Contact limit reached on your plan` | Your plan's contact limit was reached part way through. Upgrade, or remove contacts you no longer need, then import the skipped rows. |
| `Failed to save contact`             | Something went wrong saving that row. Import it again.                                                                                |

Fix the rows, save them as a new CSV, and import that file.

## Large imports on a new account

<Warning>
  Importing 5,000 or more contacts in your organization's first 24 hours holds your sending for a
  manual review. The contacts are still imported; what's held is sending to them. See
  [Deliverability overview](/deliverability/overview).
</Warning>

Buying or scraping lists is the most common source of spam complaints, so a large list arriving
before an account has any sending history gets a human look first.

## Troubleshooting

<AccordionGroup>
  <Accordion title="The file won't upload" icon="circle-alert">
    **Why:** only `.csv` files of up to 10 MB are accepted. **Fix:** export your spreadsheet as CSV.
    If it's larger than 10 MB, split it into several files and import each one.
  </Accordion>

  <Accordion title="Import stays greyed out on the Review step" icon="circle-alert">
    **Why:** you haven't confirmed consent. **Fix:** tick **I have obtained explicit consent for
    communication from all contacts in this upload**. If you saved the upload as a list, you also
    need a **List name**.
  </Accordion>

  <Accordion title="Almost every row will be skipped due to errors" icon="circle-alert">
    **Why:** no column is mapped to **Email**, so every row looks like it has no address.
    **Fix:** go **Back** to **Map Columns** and set your email column to **Email**.
  </Accordion>

  <Accordion title="Names didn't import" icon="circle-alert">
    **Why:** dashboard imports don't save the **First Name** and **Last Name** columns.
    **Fix:** edit the contacts after importing, or import through the API with the columns mapped
    to `first_name` and `last_name`.
  </Accordion>
</AccordionGroup>

## Export contacts

Export your contacts to back them up, move them to another tool, or work on them in a spreadsheet.
The file is built in the background, and you download it from your export history.

<Steps>
  <Step title="Choose who to export">
    Go to **Contacts > Import & Export** and open the **Export** tab. Under **New export**, pick
    **All contacts**, **Active contacts**, **One list** or **One segment**. For a list or a segment,
    you choose which one next.
  </Step>

  <Step title="Pick the columns">
    In the **Export Contacts** dialog, tick the **Columns** you want: **First Name**, **Last Name**,
    **Email**, **Phone Number**, **Timezone**, **Language**, **Tags** and **Notes**. The **Email**
    column holds each contact's primary email address.
  </Step>

  <Step title="Start it and download it">
    Check the **File preview**, then select **Start Export**. The export appears under
    **Export history** as **Processing**; when it reads **Completed**, select the download icon on
    its row. A **Failed** export has to be started again.

    <Screenshot id="ss-contacts-importing-03-export-history" alt="Export history with one export Processing and an older one Completed with a download button" />
  </Step>
</Steps>

Exports are always CSV files. The first row holds the column names as field keys: `firstName`,
`lastName`, `email`, `phoneNumber`, `timezone`, `language`, `tags`, `notes`. There's one row per
contact, and empty values are left blank.

<Warning>
  The **Phone Number** and **Tags** columns are exported empty. To get phone numbers or tags in
  bulk, read contacts through the [API](/api-reference/introduction) instead.
</Warning>

Each download link is fresh and short-lived, so selecting the download icon again opens a new one.
An export's **Description**, such as `List: Newsletter`, is fixed when it starts, so it keeps the
list or segment name even if you rename it later.

## Related

<Columns cols={2}>
  <Card title="Lists" icon="list" href="/contacts/lists">
    The list your upload can be saved as.
  </Card>

  <Card title="Deliverability overview" icon="shield-check" href="/deliverability/overview">
    What holds a large first send, and for how long.
  </Card>

  <Card title="Migrate from another provider" icon="arrow-right-left" href="/migrations/run-a-migration">
    Bring contacts, lists and suppressions across in one run.
  </Card>

  <Card title="Segments" icon="filter" href="/contacts/segments">
    Build the group you want to export.
  </Card>
</Columns>
