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:
| Column | Field |
|---|---|
| 1 | UID |
| 2 | |
| 3 | Email verified |
| 4–5 | Password hash, salt |
| 6–7 | Display name, photo URL |
| 8–23 | Google, Facebook, Twitter, GitHub (ID, email, name, photo each) |
| 24–25 | Created, last sign-in (milliseconds) |
| 26 | Phone 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
onDeleteCloud 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
DELETEto 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, thatonDeletefunctions won’t run.
User export and bulk actions are part of Firedeck Pro.