---
title: "Come importare contatti CSV o Excel in Brevo con uno script (Python, Node.js, cURL)"
description: "Importa in massa i contatti da un file CSV o Excel in Brevo usando l'API import-contacts. Include script Python e Node.js pronti all'uso, un one-liner cURL, gestione degli errori e consigli per file più grandi di 10 MB."
url: https://tajo.io/it/blog/import-csv-contacts-to-brevo-with-a-script/
markdown: https://tajo.io/it/blog/import-csv-contacts-to-brevo-with-a-script.md
lang: it-IT
author: "Set Noa"
author_url: https://tajo.io/it/set-noa/
published: 2026-04-30
updated: 2026-05-24
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, 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, ru-RU: /ru/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}
---

[Sincronizzazione dei dati](https://tajo.io/it/blog/?category=data-sync)

# Come importare contatti CSV o Excel in Brevo con uno script (Python, Node.js, cURL)

Importa in massa i contatti da un file CSV o Excel in Brevo usando l'API import-contacts. Include script Python e Node.js pronti all'uso, un one-liner cURL, gestione degli errori e consigli per file più grandi di 10 MB.

import csv contacts to brevo

Qual è l'endpoint dell'API Brevo per l'importazione in massa dei contatti?

Usa POST /v3/contacts/import. Passa il CSV come fileBody (≤10 MB), il JSON come jsonBody, oppure un URL via fileUrl per i file grandi. L'endpoint è asincrono e restituisce un processId. Più sotto trovi esempi in Python, Node.js e cURL.

[Scopri di più](https://tajo.io/it/blog/import-csv-contacts-to-brevo-with-a-script/#lendpoint-a-colpo-docchio)

| Campo di origine | Campo di destinazione | Valore di esempio |
| --- | --- | --- |
| `EMAIL` | `EMAIL` | `alex@example.com` |
| `FIRSTNAME` | `FIRSTNAME` | `Alex` |
| `LASTNAME` | `LASTNAME` | `Example` |

Se hai mai dovuto spingere qualche migliaio di contatti da un foglio di calcolo in Brevo, sai che la strada manuale dell’interfaccia diventa pesante in fretta: scegli il file, mappa le colonne, scegli una lista, aspetti, ripeti. Uno script fa lo stesso lavoro in pochi secondi e (cosa più importante) puoi rilanciarlo in modo programmato, dopo un export del database o ogni volta che il tuo CRM sputa fuori un nuovo CSV.

Questa guida copre l’endpoint dell’API che Brevo ti dà esattamente per questo, con script completi e funzionanti in Python, Node.js e un one-liner cURL. Tutto in questa guida colpisce **`POST /v3/contacts/import`**.

## L’endpoint a colpo d’occhio

```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
}
```

La risposta torna in fretta:

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

Quello è un 202 Accepted, Brevo ha accettato l’importazione e la sta processando in background. Il `processId` è la tua maniglia di tracking se vuoi fare polling per il completamento o configurare un webhook `notifyUrl`.

Qualche punto da conoscere prima di scrivere codice:

- **Il body può essere CSV (`fileBody`), JSON (`jsonBody`) o un URL remoto (`fileUrl`).** Sceglierne uno. La forma CSV usa il punto e virgola (`;`) per separare le colonne, non la virgola, è una trappola classica.
- **`fileBody` e `jsonBody` sono limitati a 10 MB.** Brevo consiglia di stare attorno agli 8 MB per andare sul sicuro. Per qualsiasi cosa più grande, carica il file su S3, GCS o un qualsiasi host HTTPS e passa `fileUrl` invece.
- **Gli attributi personalizzati che non esistono nel tuo account vengono ignorati silenziosamente.** Creali nell’interfaccia di Brevo (o tramite l’API Attributes) prima di importare righe che li usano, altrimenti i dati spariscono e basta.
- **`updateExistingContacts` è di default `true`.** Se lo metti su `false`, Brevo salta i contatti la cui email esiste già, utile per i job “aggiungi solo nuovi”.
- **`emptyContactsAttributes`** controlla se le celle vuote nel tuo CSV cancellano i valori esistenti. Default `false` (le celle vuote vengono ignorate). Mettilo su `true` se il tuo CSV è la fonte di verità e vuoi che i vuoti puliscano i dati obsoleti.

## Ottenere una API key

Accedi a Brevo → **Impostazioni → SMTP & API → API Keys** → crea una nuova chiave. Ha la forma `xkeysib-...`. La passerai come header HTTP `api-key` a ogni richiesta. Trattala come una password, ha accesso completo in lettura e scrittura sul tuo account.

Pratica pulita: mettila in una variable d’ambiente così non finisce mai nel tuo source tree.

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

## Python: leggere un CSV, mandarlo a Brevo

Questo è lo script più semplice possibile: leggere un CSV locale con la libreria standard, mandare il body direttamente a Brevo. Non serve nessun SDK di terze parti oltre a `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}")
```

Eseguilo:

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

La prima riga del tuo CSV è l’header. I nomi di colonna vengono mappati agli attributi Brevo per **maiuscolo, corrispondenza esatta**: `EMAIL`, `FIRSTNAME`, `LASTNAME`, oltre a qualsiasi attributo personalizzato che hai definito. `EMAIL` è obbligatorio.

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

Quello è tutto il flusso. Lo script ritorna entro un secondo, l’importazione vera gira lato server e impiega da pochi secondi a qualche minuto a seconda del volume.

## File Excel: tre strade percorribili

L’endpoint di importazione di Brevo non legge `.xlsx` direttamente, quindi hai tre opzioni reali a seconda di dove deve vivere il lavoro:

1. **Lanciare una macro VBA dentro la cartella di lavoro**, sincronizzazione in un clic da Excel stesso, senza script esterno. È la risposta giusta quando il file vive su un desktop e il tuo team vuole un pulsante sul foglio. Codice completo nella [guida alla macro VBA da Excel a Brevo](https://tajo.io/it/blog/import-excel-contacts-to-brevo-with-vba-macro).
2. **Office Scripts + Power Automate**, se la cartella di lavoro è in OneDrive/SharePoint e vuoi sincronizzazione programmata e non presidiata. Coperto anche nella [guida a Excel](https://tajo.io/it/blog/import-excel-contacts-to-brevo-with-vba-macro).
3. **Convertire `.xlsx` in CSV da uno script**, ciò che copre il resto di questa sezione. Migliore se stai già facendo girare Python o Node su un server e ti serve solo tirare dentro una cartella di lavoro una volta al giorno.

Per l’opzione 3, pandas lo fa in una riga:

```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")
```

Se non vuoi pandas come dipendenza, anche `openpyxl` da solo funziona:

```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: stesso lavoro, SDK ufficiale

Brevo pubblica `@getbrevo/brevo` per Node. Si occupa di auth, retry e della forma tipata della richiesta:

```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}`);
```

O, se non vuoi l’SDK, un semplice `fetch` funziona allo stesso modo:

```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: un one-liner per importazioni ad hoc

Quando vuoi solo testare l’endpoint o spingere a mano un piccolo file:

```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 .` ingoia tutto il file e lo escapa come JSON, ti risparmia di fare l’escape manuale di newline e virgolette.

## File più grandi di 10 MB: usa `fileUrl`

`fileBody` è limitato a 10 MB. Se il tuo dump di contatti è più grande, ospita il file a un URL che Brevo possa scaricare e passa quello:

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

Funziona qualsiasi cosa raggiungibile via un URL HTTPS pubblico, URL prefirmati S3, GCS, il tuo host statico, anche un raw URL GitHub per importazioni una tantum. Brevo scarica il file dal tuo URL, poi lancia l’importazione. Formati accettati: `.csv`, `.txt`, `.json`.

## Inviare JSON invece di CSV

Se stai già tirando i contatti da un database, non serve fare il giro tramite CSV, mandali direttamente come 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],
}
```

Stesso limite di 10 MB. Stesso comportamento asincrono.

## Polling per il completamento

L’importazione è asincrona, `processId` è la tua maniglia per seguirla. C’è un endpoint separato per controllare lo stato del processo:

```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}")
```

Per i job lunghi, il pattern più pulito è `notifyUrl`: passa un endpoint HTTPS al quale Brevo farà POST quando l’importazione finisce, e risparmiati il polling.

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

## Errori comuni e come risolverli

**`400 Bad Request` senza causa ovvia.** Quasi sempre punto e virgola contro virgole nel CSV. L’importazione di Brevo si aspetta `;`, non `,`. Ricontrolla `fileBody` dopo il tuo passo di conversione.

**I valori degli attributi personalizzati spariscono.** L’attributo non esiste nel tuo account. Crealo in **Contatti → Impostazioni → Attributi del contatto** prima di importare, oppure usa l’[API Attributes](https://developers.brevo.com/reference/create-attribute) per crearlo come parte del tuo script.

**`401 Unauthorized`.** Nome dell’header sbagliato. È `api-key` (minuscolo, con trattino), non `Authorization` né `X-API-Key`.

**Importazione “andata bene” ma i contatti non compaiono nella lista.** Controlla che `listIds` contenga la lista giusta. Inoltre: se `updateExistingContacts` è `false` e i contatti già esistono, Brevo li salta in silenzio invece di riaggiungerli alla lista.

**Alcune righe importate, altre no.** Brevo ti manda un report errori riga per riga via email dopo che l’importazione è finita (a meno che tu non imposti `disableNotification: true`). Il report ti dice quali righe avevano email errate, campi obbligatori mancanti o problemi di formattazione.

## Quando scriptare e quando usare l’interfaccia

L’interfaccia va bene per importazioni una tantum sotto le mille righe. Uno script vince non appena:

- Importi più di una volta (per esempio, export settimanale dal tuo CRM)
- I dati di origine hanno bisogno di pulizia prima di atterrare in Brevo (deduplicazione, formattazione dei numeri di telefono, suddivisione dei nomi completi in nome e cognome)
- Vuoi che giri in modo programmato senza che nessuno clicchi
- Il file è più grande della zona di comfort dell’interfaccia

Avvolgi lo script qui sopra in un cron job o in una GitHub Action e hai sincronizzazione automatica dei contatti. Il prossimo post di questa serie mostra come fare la stessa cosa direttamente da un Google Sheet usando Apps Script, senza server.

## Letture aggiuntive

- [API Brevo: riferimento Import contacts](https://developers.brevo.com/reference/import-contacts)
- [API Brevo: attributi del contatto](https://developers.brevo.com/reference/create-attribute)
- [Costruire liste di contatti per le tue campagne email](https://help.brevo.com/hc/en-us/articles/209499265)

## Domande frequenti

**Qual è l'endpoint dell'API Brevo per l'importazione in massa dei contatti?**

POST https://api.brevo.com/v3/contacts/import. Accetta contenuto CSV (fileBody), un URL di file remoto (fileUrl) o un array JSON (jsonBody). L'endpoint è asincrono, restituisce subito un processId e completa l'importazione in background.

**Qual è la dimensione massima del file?**

10 MB per CSV inline (fileBody) o JSON (jsonBody). Per file più grandi, ospita il file in un posto raggiungibile e passa il suo URL via fileUrl, quella strada non ha un limite di dimensione documentato.

**Come importo un file .xlsx?**

L'API di importazione di Brevo accetta solo .csv, .txt o .json. Converti prima il .xlsx in .csv, pandas, openpyxl o LibreOffice headless lo fanno in una riga. Lo script in questa guida include una conversione xlsx in csv.

**Sovrascrive i contatti esistenti?**

Di default sì, updateExistingContacts è impostato su true e fa il match sull'email. Mettilo su false per saltare i contatti che già esistono. Imposta emptyContactsAttributes su true se vuoi che le celle vuote del CSV cancellino i valori esistenti (altrimenti le celle vuote vengono ignorate).

## Articoli correlati

### [Importare contatti da Google Sheets a Brevo con Apps Script](https://tajo.io/it/blog/import-google-sheet-contacts-to-brevo-apps-script/)

30 apr 2026 · 3 min di lettura

Google Sheets → Brevo

### [Come spingere i contatti Excel in Brevo con una macro VBA (e l'alternativa Office Scripts)](https://tajo.io/it/blog/import-excel-contacts-to-brevo-with-vba-macro/)

30 apr 2026 · 7 min di lettura

Microsoft Excel → Brevo

### [Esportazione dati e migrazione da Brevo: come spostare i tuoi dati dentro o fuori](https://tajo.io/it/blog/brevo-data-export-migration/)

19 ago 2026 · 11 min di lettura

8 sezioni
