How to export Firebase Auth users to CSV

Adam Gelatka

You want a list of your users in a spreadsheet: for a newsletter, a support lookup, or because someone asked how many signed up with Apple. The Firebase console shows your users but has no export button.

The CLI

The Firebase CLI does it in one line:

firebase auth:export users.csv --format=csv --project my-project

or as JSON:

firebase auth:export users.json --format=json --project my-project

The file extension wins over --format, so users.json is JSON either way.

Before you send that file to anyone:

It contains password hashes. For email/password users you get the scrypt passwordHash and salt, base64-encoded. That’s what lets you migrate users to another Firebase project with auth:import. It’s also why the file shouldn’t sit in a shared Drive folder. You need the Editor or Owner role to export them.

The CSV has no header row. Every line also ends with a trailing comma. The first columns are:

ColumnField
1UID
2Email
3Email verified
4–5Password hash, salt
6–7Display name, photo URL
8–23Google, Facebook, Twitter, GitHub (ID, email, name, photo each)
24–25Created, last sign-in (milliseconds)
26Phone number

Current CLI versions add more after that: disabled, custom claims, then Apple, Microsoft, Game Center, Play Games, LinkedIn and Yahoo. The docs don’t list them yet. For anything you’ll process with code, use JSON. It has named fields, plus disabled, customAttributes, mfaInfo and providerUserInfo.

To strip the hashes from the JSON before sharing it:

jq '.users |= map(del(.passwordHash, .salt))' users.json > users-clean.json

Disabling many users

The console disables one account at a time, from each row’s menu. There’s no bulk option. With the Admin SDK it’s a loop:

import { getAuth } from 'firebase-admin/auth';

const auth = getAuth();
for (const uid of uidsToDisable) {
  await auth.updateUser(uid, { disabled: true });
}

Sequential on purpose: Auth has per-project rate limits on account updates, and a burst of parallel calls is a good way to hit them.

Deleting many users

deleteUsers takes up to 1,000 UIDs per call and is limited to about one call per second:

const chunks = [];
for (let i = 0; i < uids.length; i += 1000) chunks.push(uids.slice(i, i + 1000));

for (const chunk of chunks) {
  const result = await auth.deleteUsers(chunk);
  console.log(`deleted ${result.successCount}, failed ${result.failureCount}`);
  await new Promise((r) => setTimeout(r, 1000));
}

Two things that bite:

  • Bulk deletes don’t trigger your onDelete Cloud Functions. If a function cleans up the user’s Firestore data or Storage files, it won’t run. Clean up yourself.
  • There’s no undo. A deleted user can’t be restored. You can re-import them from an export with the hashes, but they get their account back, not their sessions. Export first.

From a phone

In Firedeck, open Authentication, tap Select, and pick users (or all of them):

  • Export to CSV or JSON. The CSV has a header row, and password hashes and salts are never included. Firedeck uses an allow-list of fields, so a new sensitive field in the API can’t slip into the file.
  • Disable or enable many users at once.
  • Delete, with guard rails: you type DELETE to confirm, by default only already-disabled users are deleted, and Firedeck saves a list of the deleted accounts for you to keep. It tells you, as I just did, that onDelete functions won’t run.

User export and bulk actions are part of Firedeck Pro.

Manage Firebase from your iPhone and iPad.

Download on the App Store