FirexportGuides

Comment importer du CSV et du JSON dans Firestore

La console Firebase ajoute les documents Firestore un par un, avec Ajouter un document (Add document), et n’a aucun bouton pour charger un fichier. L’import fourni par Google, gcloud firestore import, ne lit que les fichiers d’export propres à Firestore, pas le CSV ni le JSON. Il existe trois façons de faire entrer un fichier dans une collection. Celle qui convient dépend de la taille du fichier et de sa provenance.

Mis à jour le 21 octobre 2026. Firexport, l’extension de la méthode 1, est la nôtre. Les méthodes 2 et 3 n’en ont pas besoin.

La réponse courte

  • Un fichier CSV ou JSON dans une collection, tout de suite: importez-le depuis la vue en panneaux (Panel view) de la console avec une extension de navigateur. Méthode 1
  • Un très gros fichier, une tâche planifiée, ou des conversions à votre façon: un court script Admin SDK. Méthode 2
  • Une base de données entière depuis un autre projet ou une sauvegarde: export et import gérés avec gcloud (l’import ne lit ni le CSV ni le JSON). Méthode 3
1. Console + extension2. Script Admin SDK3. Import géré avec gcloud
Mise en placeInstaller une extension Chrome, connecter votre compte GoogleNode.js et des identifiants Google CloudUn bucket Cloud Storage et gcloud
LitCSV, JSON, JSON Lines ou texte colléCSV, JSON, JSON Lines (ce que votre code lit)Uniquement les fichiers d’export propres à Firestore
Types de champsChoisis champ par champ, avec un aperçuCe que votre code convertitConservés depuis l’export
Documents existantsLaisser, remplacer ou fusionnerCréer, remplacer ou fusionnerÉcrasés
Facturation activéeInutileInutileObligatoire (formule Blaze)

1. Importer depuis la console Firebase avec Firexport

Firexport est une extension Chrome gratuite qui ajoute une icône d’import à la vue en panneaux (Panel view) de Firestore, au bout à droite de la ligne Ajouter un document (Add document) de chaque collection. Elle écrit avec un compte Google que vous connectez : aucune clé de compte de service ni code à configurer.

  1. Installez Firexport depuis le Chrome Web Store.
  2. Dans la console Firebase, ouvrez Firestore Database > Données (Data) en vue en panneaux (Panel view) et cliquez sur la collection dans laquelle importer.
  3. Cliquez sur l’icône d’import au bout à droite de la ligne Ajouter un document (Add document).
  4. Choisissez ou déposez un fichier CSV, JSON ou JSON Lines, ou passez à Coller du texte et cliquez sur Lire.
  5. Vérifiez le type de chaque champ et la provenance des ID de documents, et choisissez ce qui se passe si un document existe déjà.
  6. La première fois, la fenêtre vous demande de Connecter un compte Google : choisissez le compte qui peut écrire dans le projet et autorisez l’accès dans la fenêtre de Google. Cliquez ensuite sur Importer.
La vue en panneaux de Firestore dans la console Firebase, avec l’icône d’import que Firexport ajoute au bout de la ligne Ajouter un document
L’icône d’import se trouve au bout à droite de la ligne Ajouter un document, dans la collection à remplir.
La fenêtre d’import après la lecture d’un CSV : trois documents, huit champs et un type choisi pour chaque champ
Chaque colonne devient un champ avec un type suggéré. La colonne Document ID fournit les ID.

Types de champs et ID de documents

  • Les cellules CSV sont du texte, et le JSON n’a ni horodatages ni références. Firexport suggère donc un type pour chaque champ d’après ses valeurs : Chaîne, Entier, Nombre (double), Booléen, Horodatage, Référence, Point géographique ou Octets (base64), ou Ne pas importer. Il n’en suggère un que si toutes les valeurs y correspondent, et vous pouvez tous les changer.
  • Les horodatages peuvent être au format ISO 8601 (2026-10-01T09:30:00Z), 2026-10-01 09:30:00 dans le fuseau horaire de votre navigateur, ou en millisecondes. Les références peuvent être un chemin comme users/u1. Les valeurs dans les maps et les tableaux gardent leur type JSON, donc les données imbriquées ont leur place dans du JSON : une colonne CSV est toujours un seul champ de premier niveau.
  • Les ID de documents viennent d’une colonne que vous choisissez, des clés d’un objet JSON, ou sont de nouveaux ID aléatoires. Une colonne Document ID est choisie pour vous, donc un fichier exporté par Firexport s’importe tel quel. Les ID écrits comme des chemins, par exemple /users/u1, utilisent leur dernier segment.
  • Un aperçu montre le premier document tel qu’il sera écrit, avec le type de chaque valeur. Les lignes qui ne peuvent pas être écrites, comme une valeur qui ne correspond pas à son type ou un ID répété, sont listées et laissées de côté avant tout envoi.

Si un document existe déjà

Le laisser, le choix par défaut, ne crée que de nouveaux documents : les lignes dont l’ID existe déjà échouent et sont listées. Le remplacer donne au document exactement les champs du fichier. Le fusionner écrit les champs du fichier, y compris dans les maps, et conserve les autres champs du document. Les nouveaux ID aléatoires ne correspondent jamais à un document existant.

Les trois choix pour les documents existants, un aperçu du premier document avec ses types et le bouton Importer 3 documents
La fenêtre indique où vont les documents avant que vous ne lanciez l’import.

Chaque document correspond à une écriture Firestore, facturée au projet. Firexport envoie jusqu’à 500 écritures par seconde et relance celles qui ont échoué pour une raison temporaire. Quand toutes les lignes sont écrites, la fenêtre se ferme avec une courte notification ; si certaines ont échoué, elle les liste, propose un rapport CSV et peut reprendre. Les écritures utilisent les autorisations du compte connecté, donc les règles de sécurité ne s’appliquent pas. Votre fichier va de votre navigateur directement chez Google, et jamais chez nous. Les fichiers et le texte collé peuvent atteindre 100 Mo.

Importez un fichier CSV ou JSON dans Firestore depuis la console, sans script ni clé de compte de service.

Ajouter à Chrome — gratuit

2. Importer avec un script Admin SDK

Pour un fichier de plus de 100 Mo, un import qui s’exécute selon un planning, ou des conversions à votre façon, un script Node.js avec le SDK Admin Firebase écrit lui-même les lignes. Celui ci-dessous lit un CSV avec une ligne d’en-tête, un tableau JSON, un objet JSON indexé par ID de document, ou du JSON Lines, et écrit un document par ligne. Il lui faut un compte qui peut écrire dans Firestore : un Propriétaire ou un Éditeur du projet, ou le rôle Utilisateur Cloud Datastore.

  1. Installez le SDK et un analyseur CSV : npm install firebase-admin csv-parse
  2. Connectez-vous pour obtenir des identifiants locaux : gcloud auth application-default login. Sur un serveur, faites plutôt pointer GOOGLE_APPLICATION_CREDENTIALS vers une clé de compte de service.
  3. Enregistrez le script ci-dessous sous import-to-firestore.mjs, remplacez your-project-id, réglez TYPES selon vos champs, et exécutez node import-to-firestore.mjs orders.csv orders.
// Usage: node import-to-firestore.mjs orders.csv orders   → one document per row in orders
// Reads .csv (with a header row), .json (an array, or an object keyed by document ID) and .jsonl.
import { readFileSync } from 'node:fs';
import { initializeApp } from 'firebase-admin/app';
import { getFirestore, Timestamp } from 'firebase-admin/firestore';
import { parse } from 'csv-parse/sync';

initializeApp({ projectId: 'your-project-id' });
const db = getFirestore();
const [file, collection] = process.argv.slice(2);
if (!file || !collection) throw new Error('Usage: node import-to-firestore.mjs <file> <collection>');

// The column or key that holds each document's ID. Rows without one get a random ID.
const ID_FIELD = 'Document ID';
// CSV cells are all text and JSON has no timestamps: list the fields to convert. The rest stay as they are.
const TYPES = { createdAt: 'timestamp', items: 'integer', total: 'number' };
// 'create' never touches an existing document (that row fails), 'set' replaces it, 'merge' adds to it.
const MODE = 'create';

const text = readFileSync(file, 'utf8');
const isCsv = file.endsWith('.csv');
let rows;
if (isCsv) {
  rows = parse(text, { columns: true, bom: true, skip_empty_lines: true });
} else if (file.endsWith('.jsonl')) {
  rows = text.split('\n').filter((line) => line.trim()).map((line) => JSON.parse(line));
} else {
  const json = JSON.parse(text);
  rows = Array.isArray(json) ? json : Object.entries(json).map(([id, data]) => ({ [ID_FIELD]: id, ...data }));
}

function convert(type, value) {
  if (type === 'timestamp') {
    const date = new Date(/^\d+$/.test(value) ? Number(value) : value); // ISO 8601 or milliseconds
    if (Number.isNaN(date.getTime())) throw new Error(`not a timestamp: ${value}`);
    return Timestamp.fromDate(date);
  }
  if (type === 'integer' || type === 'number') {
    const number = Number(value);
    if (value === '' || !Number.isFinite(number) || (type === 'integer' && !Number.isInteger(number))) {
      throw new Error(`not ${type === 'integer' ? 'an integer' : 'a number'}: ${value}`);
    }
    return number;
  }
  if (type === 'boolean') return value === true || value === 'true';
  return value;
}

// Convert every row before writing anything, so a bad value stops the import instead of half of it.
const docs = rows.map((row, index) => {
  const data = {};
  for (const [field, value] of Object.entries(row)) {
    if (field === ID_FIELD || (isCsv && value === '')) continue; // an empty CSV cell is a missing field
    try {
      data[field] = TYPES[field] ? convert(TYPES[field], value) : value;
    } catch (error) {
      throw new Error(`Row ${index + 1}, ${field}: ${error.message}`);
    }
  }
  const id = row[ID_FIELD] ? String(row[ID_FIELD]).split('/').pop() : undefined; // a path keeps its last part
  return { row: index + 1, ref: id ? db.collection(collection).doc(id) : db.collection(collection).doc(), data };
});

// BulkWriter sends the writes in batches, keeps under Firestore's rate limits and retries what can be retried.
const writer = db.bulkWriter();
const failures = [];
for (const { row, ref, data } of docs) {
  const write = MODE === 'create' ? writer.create(ref, data) : writer.set(ref, data, { merge: MODE === 'merge' });
  write.catch((error) => failures.push(`Row ${row} (${ref.id}): ${error.message}`));
}
await writer.close();
console.log(`Wrote ${docs.length - failures.length} of ${docs.length} documents to ${collection}`);
failures.forEach((failure) => console.log(failure));
  • Les cellules CSV sont du texte : le script ne convertit que les champs listés dans TYPES et garde les autres comme chaînes. Une cellule vide devient un champ absent. Les valeurs JSON gardent leur type, et les maps et les tableaux sont écrits tels quels, sauf un tableau placé directement dans un autre tableau, que Firestore refuse.
  • Toutes les lignes sont converties avant la moindre écriture : une valeur incorrecte arrête donc le script en indiquant sa ligne et son champ, au lieu de laisser un import à moitié fait.
  • Avec MODE réglé sur 'create', les documents existants restent intacts et leurs lignes sont listées comme en échec. 'set' les remplace et 'merge' y ajoute les champs du fichier. Les lignes sans ID reçoivent un nouvel ID aléatoire à chaque exécution : exécuter le script deux fois les duplique donc.
  • BulkWriter regroupe les écritures par lots, démarre à 500 par seconde et accélère autant que la règle 500/50/5 de Firestore le permet, et relance les écritures qui ont échoué pour une raison temporaire. La collection peut être un chemin de sous-collection, comme users/u1/orders. Comme la méthode 1, le script contourne les règles de sécurité, et chaque document correspond à une écriture.

3. Copier une base de données entière avec l’import géré de gcloud

gcloud firestore import, également disponible sur la page Importer/Exporter (Import/Export) de Firestore dans la console Google Cloud, est l’import géré de Firestore. Il ne lit que ce que gcloud firestore export a écrit dans un bucket Cloud Storage, au format propre de Firestore, pas du CSV ni du JSON. Utilisez-le pour restaurer une sauvegarde, ou pour copier des collections d’un projet ou d’une base de données à l’autre en gardant leurs types intacts.

# 1. Export the collection from the source project.
gcloud firestore export gs://YOUR_BUCKET/orders-export --collection-ids=orders --project=source-project-id

# 2. Import that export into the destination project.
gcloud firestore import gs://YOUR_BUCKET/orders-export --project=destination-project-id
  • La facturation doit être activée (formule Blaze). L’import compte une écriture par document.
  • Un import écrase les documents de même ID et laisse les autres documents en place. Il ne déclenche pas Cloud Functions.
  • Votre compte a besoin du rôle Propriétaire, Propriétaire Cloud Datastore ou Administrateur d’importation/exportation Cloud Datastore. Pour importer depuis le bucket d’un autre projet, l’agent de service Firestore du projet de destination, service-PROJECT_NUMBER@gcp-sa-firestore.iam.gserviceaccount.com, doit avoir accès à ce bucket.

FAQ

La console Firebase peut-elle importer un fichier CSV ou JSON dans Firestore ?

Non. L’onglet Données (Data) de Firestore ajoute les documents un par un avec Ajouter un document (Add document), et gcloud firestore import ne lit que les fichiers d’export propres à Firestore. Pour charger un fichier CSV ou JSON, il faut un script Admin SDK, ou une extension de navigateur comme Firexport qui ajoute un import à la console.

Comment importer un fichier JSON dans Firestore ?

Utilisez un tableau JSON d’objets, un par document, ou un objet indexé par ID de document. Dans Firexport, cliquez sur l’icône d’import de la ligne Ajouter un document (Add document) de la collection et choisissez le fichier ; les maps et les tableaux gardent leur type JSON. Avec le SDK Admin, lisez le fichier et écrivez chaque objet avec BulkWriter, comme dans le script ci-dessus.

Comment les horodatages et les références sont-ils importés ?

Le CSV et le JSON ne peuvent pas porter les types Firestore : un horodatage dans un fichier n’est donc que du texte tant que rien ne le convertit. Firexport le convertit quand vous réglez le type du champ sur Horodatage, Référence ou Point géographique. Dans un script, convertissez-le vous-même, par exemple avec Timestamp.fromDate(new Date(value)) ou db.doc(path).

Les règles de sécurité s’appliquent-elles à un import ?

Non. L’import de Firexport, le SDK Admin et gcloud écrivent tous avec les autorisations IAM d’un compte, et les règles de sécurité ne s’appliquent qu’aux SDK client. Vérifiez les données, et le compte, avant d’importer.

Combien coûte un import dans Firestore ?

Chaque document importé correspond à une écriture, quelle que soit la méthode. Avec la formule Spark gratuite, cela entre dans les 20 000 écritures par jour, et les écritures au-delà échouent jusqu’à la réinitialisation du quota. Avec Blaze, les écritures au-delà du quota gratuit sont facturées au tarif de l’emplacement de votre base de données.