---
title: "Как импортировать контакты из CSV или Excel в Brevo с помощью скрипта (Python, Node.js, cURL)"
description: "Массовый импорт контактов из CSV или Excel-файла в Brevo через API import-contacts. Включает готовые скрипты на Python и Node.js, однострочник на cURL, обработку ошибок и советы для файлов больше 10 MB."
url: https://tajo.io/ru/blog/import-csv-contacts-to-brevo-with-a-script/
markdown: https://tajo.io/ru/blog/import-csv-contacts-to-brevo-with-a-script.md
lang: ru-RU
author: "Set Noa"
author_url: https://tajo.io/ru/set-noa/
published: 2026-04-30
updated: 2026-05-09
alternates: {en-US: /blog/import-csv-contacts-to-brevo-with-a-script.md, bg-BG: /bg/blog/import-csv-contacts-to-brevo-with-a-script.md, cs-CZ: /cz/blog/import-csv-contacts-to-brevo-with-a-script.md, de-DE: /de/blog/import-csv-contacts-to-brevo-with-a-script.md, da-DK: /dk/blog/import-csv-contacts-to-brevo-with-a-script.md, es-ES: /es/blog/import-csv-contacts-to-brevo-with-a-script.md, fr-FR: /fr/blog/import-csv-contacts-to-brevo-with-a-script.md, el-GR: /gr/blog/import-csv-contacts-to-brevo-with-a-script.md, hi-IN: /hi/blog/import-csv-contacts-to-brevo-with-a-script.md, id-ID: /in/blog/import-csv-contacts-to-brevo-with-a-script.md, hr-HR: /hr/blog/import-csv-contacts-to-brevo-with-a-script.md, hu-HU: /hu/blog/import-csv-contacts-to-brevo-with-a-script.md, it-IT: /it/blog/import-csv-contacts-to-brevo-with-a-script.md, ja-JP: /jp/blog/import-csv-contacts-to-brevo-with-a-script.md, ko-KR: /kr/blog/import-csv-contacts-to-brevo-with-a-script.md, ar-SA: /ar/blog/import-csv-contacts-to-brevo-with-a-script.md, nl-NL: /nl/blog/import-csv-contacts-to-brevo-with-a-script.md, no-NO: /no/blog/import-csv-contacts-to-brevo-with-a-script.md, pl-PL: /pl/blog/import-csv-contacts-to-brevo-with-a-script.md, pt-BR: /pt/blog/import-csv-contacts-to-brevo-with-a-script.md, ro-RO: /ro/blog/import-csv-contacts-to-brevo-with-a-script.md, sv-SE: /se/blog/import-csv-contacts-to-brevo-with-a-script.md, zh-CN: /zh-cn/blog/import-csv-contacts-to-brevo-with-a-script.md, sl-SI: /sl/blog/import-csv-contacts-to-brevo-with-a-script.md, sr-Latn-RS: /sr/blog/import-csv-contacts-to-brevo-with-a-script.md, th-TH: /th/blog/import-csv-contacts-to-brevo-with-a-script.md, tr-TR: /tr/blog/import-csv-contacts-to-brevo-with-a-script.md, ur-PK: /ur/blog/import-csv-contacts-to-brevo-with-a-script.md, vi-VN: /vi/blog/import-csv-contacts-to-brevo-with-a-script.md, sk-SK: /sk/blog/import-csv-contacts-to-brevo-with-a-script.md}
---

[Синхронизация данных](https://tajo.io/ru/blog/?category=data-sync)

# Как импортировать контакты из CSV или Excel в Brevo с помощью скрипта (Python, Node.js, cURL)

Массовый импорт контактов из CSV или Excel-файла в Brevo через API import-contacts. Включает готовые скрипты на Python и Node.js, однострочник на cURL, обработку ошибок и советы для файлов больше 10 MB.

import csv contacts to brevo

Как импортировать контакты из CSV или Excel в Brevo с помощью скрипта?

Используйте POST /v3/contacts/import. Передавайте CSV как fileBody (≤10 MB), JSON как jsonBody или URL через fileUrl для крупных файлов. Эндпоинт асинхронный и возвращает processId. Примеры на Python, Node.js и cURL ниже.

[Узнать больше](https://tajo.io/ru/blog/import-csv-contacts-to-brevo-with-a-script/#%D1%8D%D0%BD%D0%B4%D0%BF%D0%BE%D0%B8%D0%BD%D1%82-%D0%B2%D0%BA%D1%80%D0%B0%D1%82%D1%86%D0%B5)

| Поле источника | Поле назначения | Пример значения |
| --- | --- | --- |
| `EMAIL` | `EMAIL` | `alex@example.com` |
| `FIRSTNAME` | `FIRSTNAME` | `Alex` |
| `LASTNAME` | `LASTNAME` | `Example` |

Если Вам когда-либо приходилось загружать несколько тысяч контактов из таблицы в Brevo, то путь через ручной интерфейс быстро становится утомительным: выбрать файл, сопоставить столбцы, выбрать список, ждать, повторить. Скрипт делает то же самое за секунды и, что важнее, его можно запускать снова по расписанию, после экспорта из базы данных или каждый раз, когда Ваш CRM выдаёт свежий CSV.

В этом руководстве рассматривается API-эндпоинт, который Brevo предоставляет именно для этой задачи, с полностью рабочими скриптами на Python, Node.js и однострочником на cURL. Всё в этом руководстве обращается к **`POST /v3/contacts/import`**.

## Эндпоинт вкратце

```http
POST https://api.brevo.com/v3/contacts/import
Content-Type: application/json
api-key: YOUR_API_KEY

{
  "fileBody": "EMAIL;FIRSTNAME;LASTNAME\njane@example.com;Jane;Doe",
  "listIds": [42],
  "updateExistingContacts": true,
  "emailBlacklist": false,
  "smsBlacklist": false
}
```

Ответ возвращается быстро:

```json
{ "processId": 78 }
```

Это 202 Accepted: Brevo принял импорт и обрабатывает его в фоне. `processId` будет Вашим идентификатором отслеживания, если Вы захотите опрашивать статус выполнения или настроить вебхук `notifyUrl`.

Несколько моментов, которые стоит учесть до написания кода:

- **Тело запроса может быть в формате CSV (`fileBody`), JSON (`jsonBody`) или URL удалённого файла (`fileUrl`).** Выберите один вариант. CSV-форма использует точки с запятой (`;`) для разделения столбцов, а не запятые, это типичная ошибка.
- **`fileBody` и `jsonBody` ограничены 10 MB.** Brevo рекомендует не превышать примерно 8 MB для надёжности. Для всего более крупного загрузите файл в S3, GCS или на любой HTTPS-хост и передайте `fileUrl` вместо тела.
- **Пользовательские атрибуты, отсутствующие в Вашем аккаунте, тихо игнорируются.** Создайте их в интерфейсе Brevo (или через Attributes API) до импорта строк, в которых они используются, иначе данные просто исчезнут.
- **`updateExistingContacts` по умолчанию `true`.** Если установите `false`, Brevo пропустит контакты с уже существующим email, удобно для задач “добавлять только новые”.
- **`emptyContactsAttributes`** управляет тем, будут ли пустые ячейки CSV стирать существующие значения. По умолчанию `false` (пустые ячейки игнорируются). Установите `true`, если CSV является источником истины и пустые поля должны очищать устаревшие данные.

## Получение API-ключа

Войдите в Brevo → **Settings → SMTP & API → API Keys** → создайте новый ключ. Он выглядит как `xkeysib-...`. Вы будете передавать его в HTTP-заголовке `api-key` при каждом запросе. Относитесь к нему как к паролю, у него полный доступ на чтение и запись в Вашем аккаунте.

Хорошая практика: положите ключ в переменную окружения, чтобы он никогда не попал в исходный код.

```bash
export BREVO_API_KEY="xkeysib-..."
```

## Python: прочитать CSV и отправить в Brevo

Это самый простой возможный скрипт: чтение локального CSV стандартной библиотекой и отправка тела напрямую в Brevo. Из сторонних зависимостей нужен только `requests`.

```python
import csv
import io
import os
import sys
import requests

API_KEY = os.environ["BREVO_API_KEY"]
LIST_ID = 42  # the Brevo list to add contacts to
INPUT_FILE = sys.argv[1] if len(sys.argv) > 1 else "contacts.csv"

# Brevo wants semicolon-separated CSV. If your file uses commas (most do),
# convert it on the fly so you don't have to edit the source spreadsheet.
def to_brevo_csv(path: str) -> str:
    with open(path, newline="", encoding="utf-8") as f:
        reader = csv.reader(f)  # default: comma-separated
        out = io.StringIO()
        writer = csv.writer(out, delimiter=";")
        for row in reader:
            writer.writerow(row)
        return out.getvalue()

body = {
    "fileBody": to_brevo_csv(INPUT_FILE),
    "listIds": [LIST_ID],
    "updateExistingContacts": True,
    "emptyContactsAttributes": False,
    "emailBlacklist": False,
    "smsBlacklist": False,
}

resp = requests.post(
    "https://api.brevo.com/v3/contacts/import",
    json=body,
    headers={"api-key": API_KEY, "Content-Type": "application/json"},
    timeout=60,
)

if resp.status_code != 202:
    print(f"Import failed: {resp.status_code} {resp.text}")
    sys.exit(1)

process_id = resp.json()["processId"]
print(f"Import accepted. Process ID: {process_id}")
```

Запуск:

```bash
python import_csv_to_brevo.py contacts.csv
```

Первая строка Вашего CSV - это заголовок. Имена столбцов сопоставляются с атрибутами Brevo по **точному совпадению в верхнем регистре**: `EMAIL`, `FIRSTNAME`, `LASTNAME`, плюс любые пользовательские атрибуты, которые Вы определили. `EMAIL` обязателен.

```csv
EMAIL,FIRSTNAME,LASTNAME,COMPANY,CITY
jane@example.com,Jane,Doe,Acme,Berlin
john@example.com,John,Smith,Globex,Paris
```

Это весь процесс. Скрипт возвращается в течение секунды; сам импорт идёт на стороне сервера и занимает от нескольких секунд до нескольких минут в зависимости от объёма.

## Excel-файлы: три рабочих пути

Эндпоинт импорта Brevo не читает `.xlsx` напрямую, поэтому есть три реальных варианта, в зависимости от того, где должна выполняться работа:

1. **Запустить VBA-макрос внутри книги** - синхронизация в один клик прямо из Excel, без внешнего скрипта. Правильный ответ, когда файл лежит на десктопе и Ваша команда хочет кнопку на листе. Полный код в [руководстве по VBA-макросу для Excel и Brevo](https://tajo.io/ru/blog/import-excel-contacts-to-brevo-with-vba-macro).
2. **Office Scripts + Power Automate** - если книга находится в OneDrive/SharePoint и Вы хотите автономную синхронизацию по расписанию. Тоже разобрано в [руководстве по Excel](https://tajo.io/ru/blog/import-excel-contacts-to-brevo-with-vba-macro).
3. **Преобразовать `.xlsx` в CSV из скрипта** - этому посвящён остаток этого раздела. Лучший вариант, если у Вас уже работает Python или Node на сервере и нужно подтягивать книгу раз в день.

Для варианта 3 pandas справляется в одну строку:

```python
# pip install pandas openpyxl
import pandas as pd

def xlsx_to_brevo_csv(path: str, sheet_name: str | int = 0) -> str:
    df = pd.read_excel(path, sheet_name=sheet_name)
    return df.to_csv(sep=";", index=False)

body["fileBody"] = xlsx_to_brevo_csv("contacts.xlsx")
```

Если Вы не хотите тянуть pandas как зависимость, достаточно одного `openpyxl`:

```python
from openpyxl import load_workbook
import csv, io

def xlsx_to_brevo_csv(path: str) -> str:
    wb = load_workbook(path, read_only=True)
    ws = wb.active
    out = io.StringIO()
    writer = csv.writer(out, delimiter=";")
    for row in ws.iter_rows(values_only=True):
        writer.writerow(["" if v is None else v for v in row])
    return out.getvalue()
```

## Node.js: та же задача, официальный SDK

Brevo публикует пакет `@getbrevo/brevo` для Node. Он берёт на себя авторизацию, повторные попытки и типизированную форму запроса:

```javascript
// npm install @getbrevo/brevo
import fs from 'node:fs/promises';
import { BrevoClient } from '@getbrevo/brevo';

const API_KEY = process.env.BREVO_API_KEY;
const LIST_ID = 42;
const INPUT_FILE = process.argv[2] ?? 'contacts.csv';

const client = new BrevoClient({ apiKey: API_KEY });

// Read the CSV and convert commas to semicolons if needed
const raw = await fs.readFile(INPUT_FILE, 'utf-8');
const csv = raw.includes(';') ? raw : raw.replace(/,/g, ';');

const result = await client.contacts.importContacts({
  fileBody: csv,
  listIds: [LIST_ID],
  updateExistingContacts: true,
  emptyContactsAttributes: false,
});

console.log(`Import accepted. Process ID: ${result.processId}`);
```

Или, если SDK не нужен, обычный `fetch` работает так же:

```javascript
const resp = await fetch('https://api.brevo.com/v3/contacts/import', {
  method: 'POST',
  headers: {
    'api-key': process.env.BREVO_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    fileBody: csv,
    listIds: [42],
    updateExistingContacts: true,
  }),
});

if (resp.status !== 202) {
  throw new Error(`Import failed: ${resp.status} ${await resp.text()}`);
}

const { processId } = await resp.json();
console.log(`Process ID: ${processId}`);
```

## cURL: однострочник для разовых импортов

Когда Вы просто хотите протестировать эндпоинт или вручную залить небольшой файл:

```bash
# Convert commas to semicolons, then send the file inline
csv=$(sed 's/,/;/g' contacts.csv | jq -Rs .)

curl -X POST https://api.brevo.com/v3/contacts/import \
  -H "api-key: $BREVO_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"fileBody\": $csv, \"listIds\": [42], \"updateExistingContacts\": true}"
```

`jq -Rs .` забирает весь файл и JSON-экранирует его, избавляя Вас от ручного экранирования переводов строк и кавычек.

## Файлы больше 10 MB: используйте `fileUrl`

`fileBody` ограничен 10 MB. Если Ваш дамп контактов больше, разместите файл по URL, доступному для Brevo, и передайте этот адрес:

```python
body = {
    "fileUrl": "https://files.example.com/contacts/2026-04-30.csv",
    "listIds": [42],
    "updateExistingContacts": True,
}
```

Подойдёт всё, что доступно по публичному HTTPS-URL: предподписанные ссылки S3, GCS, Ваш собственный статический хост, даже raw-URL с GitHub для разовых импортов. Brevo забирает файл по Вашему URL и затем запускает импорт. Принимаемые форматы: `.csv`, `.txt`, `.json`.

## Отправка JSON вместо CSV

Если Вы и так берёте контакты из базы данных, нет смысла гнать их через CSV, отправляйте сразу JSON:

```python
body = {
    "jsonBody": [
        {
            "email": "jane@example.com",
            "attributes": {
                "FIRSTNAME": "Jane",
                "LASTNAME": "Doe",
                "COMPANY": "Acme",
            },
        },
        {
            "email": "john@example.com",
            "attributes": {
                "FIRSTNAME": "John",
                "LASTNAME": "Smith",
                "COMPANY": "Globex",
            },
        },
    ],
    "listIds": [42],
}
```

Тот же лимит 10 MB. То же асинхронное поведение.

## Опрос статуса завершения

Импорт асинхронный, `processId` - Ваш идентификатор для его отслеживания. Есть отдельный эндпоинт для проверки статуса процесса:

```python
def wait_for_import(process_id: int, timeout_s: int = 600) -> dict:
    import time
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        r = requests.get(
            f"https://api.brevo.com/v3/processes/{process_id}",
            headers={"api-key": API_KEY},
            timeout=30,
        )
        r.raise_for_status()
        status = r.json()
        if status["status"] in ("completed", "failed"):
            return status
        time.sleep(5)
    raise TimeoutError(f"Import {process_id} did not finish in {timeout_s}s")

result = wait_for_import(process_id)
print(f"Import {result['status']}: {result}")
```

Для долго выполняющихся задач более чистый паттерн - `notifyUrl`: укажите HTTPS-эндпоинт, на который Brevo отправит POST по завершении импорта, и пропустите опрос.

```python
body["notifyUrl"] = "https://your-app.example.com/webhooks/brevo-import"
```

## Распространённые ошибки и как их исправить

**`400 Bad Request` без явной причины.** Почти всегда дело в точках с запятой против запятых в CSV. Импорт Brevo ожидает `;`, а не `,`. Проверьте `fileBody` после шага конвертации.

**Значения пользовательских атрибутов исчезают.** Атрибут не существует в Вашем аккаунте. Создайте его в **Contacts → Settings → Contact attributes** до импорта или используйте [Attributes API](https://developers.brevo.com/reference/create-attribute), чтобы создать его прямо из скрипта.

**`401 Unauthorized`.** Неправильное имя заголовка. Это `api-key` (нижний регистр, через дефис), а не `Authorization` или `X-API-Key`.

**Импорт “успешен”, но контакты не появились в списке.** Проверьте, что в `listIds` указан правильный список. Кроме того: если `updateExistingContacts` равен `false` и контакты уже существуют, Brevo молча пропускает их вместо повторного добавления в список.

**Часть строк импортирована, часть нет.** Brevo присылает Вам отчёт об ошибках по каждой строке на email после завершения импорта (если только Вы не задали `disableNotification: true`). Отчёт говорит, у каких строк были некорректные адреса, отсутствующие обязательные поля или проблемы с форматированием.

## Когда использовать скрипт, а когда интерфейс

Интерфейс подходит для разовых импортов до тысячи строк. Скрипт выигрывает, как только:

- Вы импортируете больше одного раза (например, еженедельный экспорт из Вашего CRM)
- Исходные данные нужно почистить перед загрузкой в Brevo (дедупликация, форматирование номеров телефонов, разбиение полного имени на имя и фамилию)
- Вы хотите запускать процесс по расписанию без чьих-либо кликов
- Файл больше, чем интерфейс комфортно обрабатывает

Заверните вышеуказанный скрипт в cron-задачу или GitHub Action, и Вы получите автоматическую синхронизацию контактов. Следующий пост в этой серии показывает, как сделать то же самое прямо из Google-таблицы с помощью Apps Script, без сервера.

## Дополнительные материалы

- [Brevo API: справка по импорту контактов](https://developers.brevo.com/reference/import-contacts)
- [Brevo API: атрибуты контактов](https://developers.brevo.com/reference/create-attribute)
- [Создание списков контактов для email-кампаний](https://help.brevo.com/hc/en-us/articles/209499265)

## Часто Задаваемые Вопросы

**Какой эндпоинт Brevo API отвечает за массовый импорт контактов?**

POST https://api.brevo.com/v3/contacts/import. Он принимает CSV-содержимое (fileBody), URL удалённого файла (fileUrl) или JSON-массив (jsonBody). Эндпоинт асинхронный: он сразу возвращает processId и завершает импорт в фоне.

**Какой максимальный размер файла?**

10 MB для встроенного CSV (fileBody) или JSON (jsonBody). Для файлов большего размера разместите файл по доступному адресу и передайте его URL через fileUrl, у этого пути нет задокументированного ограничения по размеру.

**Как импортировать файл .xlsx?**

Импорт-API Brevo принимает только .csv, .txt или .json. Сначала преобразуйте .xlsx в .csv, это можно сделать в одну строку с помощью pandas, openpyxl или LibreOffice headless. Скрипт в этом руководстве включает конвертацию xlsx в csv.

**Перезапишет ли импорт существующие контакты?**

По умолчанию да, updateExistingContacts установлен в true и сопоставляет контакты по email. Установите false, чтобы пропускать уже существующие контакты. Установите emptyContactsAttributes в true, если хотите, чтобы пустые ячейки CSV стирали существующие значения (иначе пустые ячейки игнорируются).

## Похожие статьи

### [Импорт контактов из Google Sheets в Brevo через Apps Script](https://tajo.io/ru/blog/import-google-sheet-contacts-to-brevo-apps-script/)

30 апр. 2026 г. · 3 мин чтения

Google Sheets → Brevo

### [Как загружать контакты из Excel в Brevo с помощью VBA-макроса (и альтернатива на Office Scripts)](https://tajo.io/ru/blog/import-excel-contacts-to-brevo-with-vba-macro/)

30 апр. 2026 г. · 6 мин чтения

Microsoft Excel → Brevo

### [Экспорт и миграция данных Brevo: как перенести данные в систему и из неё](https://tajo.io/ru/blog/brevo-data-export-migration/)

19 авг. 2026 г. · 9 мин чтения

8 разделов
