Bitwarden's five export files
Leaving Bitwarden? Skip the account-restricted JSON. Only the Bitwarden account that made it can decrypt it.
Checked against Bitwarden web vault Sources: bitwarden/clients, bitwarden/sdk-internal
The export dialog offers four file formats. The encrypted JSON comes in two kinds, password-protected and account-restricted, so there are five different files you can end up with. Which one you pick decides whether your attachments, cards and second factors come with you. We exported one vault in every form Buddy can open.
| Form | File | Encrypted |
|---|---|---|
| Plaintext JSON Highest fidelity of the five. The reference form the others are measured against. | bitwarden_export_*.json |
No |
| Password-protected JSON Decrypts to exactly the plaintext form, so nothing downstream needs to know it was encrypted. | bitwarden_encrypted_export_*.json |
Yes |
| Account-restricted JSON Shares a filename prefix with the password-protected form. Told apart by the passwordProtected key. Buddy cannot read this file. The file carries no salt, kdfType or kdfIterations, because it was never re-encrypted for export. It is a verbatim dump of ciphertext held under a server-side account key, so opening it means authenticating to Bitwarden. | bitwarden_encrypted_export_*.json |
Yes |
| CSV Cards and identities never reach the file. This is Bitwarden's own limitation, not an importer one. | bitwarden_export_*.csv |
No |
| ZIP data.json plus an attachments directory. The only form that carries files. Always plaintext; there is no encrypted zip form. | bitwarden_export_*.zip |
No |
For a move, the plaintext JSON is enough, or the ZIP if you have attachments. Use the password-protected JSON if the file will sit somewhere you do not control.
How to export
In the web vault, open Tools in the left sidebar, then Export. Pick a file format and choose Export. You will be asked for your master password.
.json
.csv
.json (Encrypted)
.zip (with attachments)
This exports your individual vault only. Items that belong to an organization are not in the file; an organization owner or admin exports those separately from the Admin Console.
Only .json (Encrypted) produces an encrypted file.
JSON format
This is the highest-fidelity form, and the reference the other four are measured against. The ZIP's
data.json is byte-identical to it for the same vault, and the password-protected form
is this document encrypted.
Document layout
A plaintext export is one object. Folders are listed once, and items point at them by id.
{
"encrypted": false,
"folders": [
{ "id": "11111111-1111-1111-1111-111111111111", "name": "Work/Dev" }
],
"items": [ ... ]
}
Item types
Every item has a numeric type, and one object named after that type holding its own
fields:
1 Login login
2 Secure note secureNote
3 Card card
4 Identity identity
5 SSH key sshKey
A login:
{
"id": "aaaaaaaa-0000-0000-0000-000000000001",
"folderId": "11111111-1111-1111-1111-111111111111",
"type": 1,
"reprompt": 0,
"name": "GitHub",
"notes": "Personal account",
"favorite": true,
"fields": [],
"login": {
"uris": [
{ "match": null, "uri": "https://github.com/login" }
],
"username": "octocat",
"password": "correct-horse-battery",
"totp": "otpauth://totp/GitHub:octocat?secret=JBSWY3DPEHPK3PXP&issuer=GitHub"
},
"passwordHistory": [
{ "lastUsedDate": "2026-03-01T10:00:00.000Z", "password": "previous-password" }
]
}
A secure note is only its name and notes. Its secureNote
object holds a single type, which is always 0. Cards import into card
fields and identities into custom fields. SSH key items import with their name, notes and custom
fields, but not the key.
Custom fields
Each entry in fields has a numeric type of its own:
"fields": [
{ "name": "Employee ID", "value": "12345", "type": 0 },
{ "name": "Recovery code", "value": "X7K2-9QPL-M4TR", "type": 1 },
{ "name": "Admin", "value": "true", "type": 2 },
{ "name": "Login alias", "type": 3, "linkedId": 100 }
]
0text imports as a text field.1hidden imports as a secret field.2boolean is the stringtrueorfalse, and imports as text.3linked has no value. It points at one of the item's own fields throughlinkedId, here100for the login's username, and is skipped.
URI match
match on each URI is its autofill rule, or null when the item follows the
account default:
0 Base domain 3 Exact
1 Host 4 Regular expression
2 Starts with 5 Never
Buddy does not read it.
Folders
There is no parent id anywhere in a Bitwarden export. A nested folder is literally named
parent/child, and the interface renders the slash as a tree. Personal exports use
folders and organization exports use collections, but both are just a
map of id to name.
The practical consequence for anything converting these to tags is that only the slash separates. Folder names contain spaces all the time, so a splitter that treats whitespace as a separator turns one folder called "child folder" into two unrelated tags.
An item in several collections keeps the first one as a tag. The rest are not recorded.
TOTP
Bitwarden does not validate what goes in the TOTP field. Real exports hold full
otpauth:// URIs, bare base32 seeds, and outright junk, sometimes all three in one vault.
Keep anything you cannot parse. A lost second factor looks fine until the day you are locked out of the account. Buddy imports an unreadable value as a secret field for you to sort out by hand.
Passkeys
A login's passkeys are written into login.fido2Credentials, private key included, in
the plaintext JSON, the password-protected JSON and the ZIP. The CSV has no column for them. That
makes a plaintext JSON export more sensitive than it looks: anyone holding the file can sign in
with those passkeys, not only read your passwords.
Encrypted JSON formats
Two of the forms are encrypted, they share a filename prefix, and they look nearly identical. They
are told apart by a single key in the file, passwordProtected.
The account-restricted form was never re-encrypted for export. It is a verbatim
dump of the ciphertext already sitting in your synced vault, encrypted under an account key that
Bitwarden holds server side. There is nothing in the file to derive a key from: no salt, no
kdfType, no kdfIterations. Opening it means authenticating to Bitwarden.
Two details in the file confirm it is raw synced state, not something generated for the export.
Each item carries its own wrapped key, and each saved URI carries a uriChecksum.
That checksum exists so a compromised Bitwarden server cannot swap a saved URI and trick autofill
into posting your credentials somewhere else. It is a defense that only makes sense inside the
sync relationship, so finding it in a file tells you the file is a copy of your synced vault.
Bitwarden's own interface calls this “account restricted” and warns that it can only be imported back into the same account. Nothing outside Bitwarden can read it. No importer is missing a feature here; the format is built that way. Re-export as password-protected instead.
ZIP format
The ZIP export is data.json plus an attachments/ directory, and it is
always plaintext, with no encrypted option. It is also the only Bitwarden export that carries the
attached files themselves.
The attachment paths carry neither the item id nor the attachment id:
attachments/<sanitized item name>[_N]/<sanitized filename stem>[_N].<ext>
Files are matched back to items by reproducing Bitwarden's own sanitizing and de-duplication rules, which means the order items are walked in is load-bearing. Two items with the same name, or two attachments with the same filename, are told apart only by a positional counter.
CSV format
Cards and identities have no rows in the CSV at all. Every item of those two types is absent from the file, and nothing in the file records that they were left out.
Also gone: attachments, password history, and the distinction between a hidden custom field and a
plain text one, since every custom field flattens to a name: value line.
Column layouts
Bitwarden added an archivedDate column as the eighth column, which pushed every login
column one position to the right.
folder,favorite,type,name,notes,fields,reprompt,archivedDate,
login_uri,login_username,login_password,login_totp (12 columns, current)
folder,favorite,type,name,notes,fields,reprompt,
login_uri,login_username,login_password,login_totp (11 columns, legacy)
Nothing errors when this goes wrong. Anything reading these files by column position rather than by header will
read archivedDate as the URL, the URL as the username, and the username as the
password, on every row, without raising an error. If you have imported a Bitwarden CSV somewhere
and the fields look shifted, this is why.
Buddy field mapping
JSON and ZIP
The plaintext JSON, the password-protected JSON once decrypted, and the ZIP's
data.json share one layout.
CSV
Every CSV export loses folders and metadata to some degree, and that is survivable. The fields that have to come through are username, password, URI, TOTP and note. Check those after any migration, from any manager, into anything.
Buddy is a desktop password manager for macOS and Windows that imports these files. If your export looks different from what this page describes, tell us. Other managers are on the export formats page.