Inside 1Password's 1PUX archive and CSV export

The CSV has rows for Login items and nothing else. Cards, identities, secure notes and attachments are only in the 1PUX.

Checked against 1Password 8 Sources: bitwarden/clients 1PUX importer

1Password 8 exports two ways: a CSV, or its own .1pux archive. Neither is encrypted, and 1Password does not pitch either one as a backup. They exist to get your data into something else.

Form File Encrypted
1PUX A ZIP holding items as JSON plus the files you attached. The richest thing 1Password will give you. *.1pux No
CSV Flat, nine columns. No attachments, no SSH keys, no custom section structure. Tags, TOTP and the archive flag do carry, which is more than most CSV exports manage. *.csv No
What survives 1PUX *.1pux CSV *.csv
Logins
1PUX Logins: Fully supported.
CSV Logins: Fully supported.
TOTP secrets
1PUX TOTP secrets: Fully supported.
CSV TOTP secrets: Fully supported.
Attachments
1PUX Attachments: Fully supported.
CSV Attachments: N/A.
Custom fields
1PUX Custom fields: Fully supported.
CSV Custom fields: N/A.
Folders
1PUX Folders: Fully supported.
CSV Folders: Fully supported.
Payment cards
1PUX Payment cards: Fully supported.
CSV Payment cards: N/A.
Password history
1PUX Password history: Fully supported.
CSV Password history: N/A.
Passkeys
1PUX Passkeys: Not yet supported.
CSV Passkeys: N/A.
Fully supported
Limited
Not yet supported
N/A

Take the .1pux unless whatever you are moving to reads nothing else. Besides every item type and your attachments, it keeps the creation dates and password history the CSV drops.

How to export

In the desktop app, choose File, then Export, then your account, and pick a format. You will be asked for your account password either way. Moving into Buddy specifically, step by step, is covered in the 1Password migration guide.

Nothing in the Trash is exported, in either format. We checked with a vault holding a trashed login and a trashed identity, and neither reached either file. If there is something in the Trash you want, restore it before you export.

1PUX format

A .1pux is a ZIP with three things in it:

export.attributes    { "version": 3, "description": ..., "timestamp": ... }
export.data          the entire vault, as one JSON document
files/               the attachments, plus each vault's avatar image

export.attributes records when the export was made. Most formats on this site carry no date inside the file, and at best put one in the filename.

export.data nests four levels deep, and two of those levels are the first thing a careless importer throws away:

accounts[]
  attrs      { accountName, name, email, uuid, domain, avatar }
  vaults[]
    attrs    { uuid, name, desc, type, avatar? }
    items[]
      uuid, favIndex, createdAt, updatedAt, state, categoryUuid
      overview { title, url, urls[], tags[], ... }
      details  { loginFields[], notesPlain, sections[], passwordHistory[], documentAttributes? }

Vault type is P for the built-in Personal vault and U for one you made. The desc is the vault's description and avatar, when present, names a file in files/.

An item's state has only two values in practice, active and archived, because the third thing an item can be is trashed and trashed items never reach the file.

Since 1Password has no folders, the vault is the only grouping an item has, and an importer that flattens accounts and vaults into one list loses it. Two entries called Netflix in two different vaults become two entries called Netflix, with nothing left to say which was which.

Field locations

An item's own fields can live in four places, and a complete reader needs all of them:

  • overview holds the title, the primary url, and tags.
  • details.loginFields[] holds the username and password, identified by a designation of username or password rather than by position or name.
  • details.sections[].fields[] holds everything else, including the TOTP secret, SSH keys, card numbers and every custom field.
  • details.password holds the one value of a Password item, category 005, which has no login fields at all.

loginFields can also hold the other inputs of the web form a login was saved from: a PIN box, a “remember me” checkbox, a terms-of-service tick. Those entries have no designation key at all, not an empty one:

{ "value": "✓", "id": "terms", "name": "terms", "fieldType": "C" }

A parser that expects every login field to carry a designation fails on the whole file the first time it meets one. Buddy keeps the named inputs as custom fields, conceals the password-type ones (fieldType P), and drops the checkboxes.

A section field's value is a single-key object where the key is the type:

{
  "id": "cvv",
  "title": "verification number",
  "value": {
    "concealed": "123"
  },
  "guarded": true,
  "multiline": false,
  "dontGenerate": false,
  "inputTraits": {...}
}

The keys observed across the exports inspected for this page are string, concealed, url, phone, menu, email, date, monthYear, address, file, sshKey, ssoLogin, totp, creditCardNumber and creditCardType. Not all of them turn up in any one vault: ssoLogin appeared in an older export and not a newer one, and creditCardType the other way round. Reading the type off the key rather than guessing from the value is what lets a concealed field stay concealed after the move.

Card fields are the exception to reading by type. On a Credit Card item the useful identity is the field's id: cardholder, ccnum, cvv, expiry and type. The expiry is an integer, so April 2028 is 202804, and an unset one is null rather than absent.

Value validation

1Password accepts almost anything in almost any field. The exceptions are the few filled through a date picker or similar widget, which normalize the input. Everything else is exported exactly as typed, so a card number field can hold this:

"value": { "creditCardNumber": "4111 1111 1111 1111 (old card, see note) " }

A parser that trusts the key and reads the value strictly will choke on the example above, so validate the value too.

Categories

categoryUuid is a string of digits. 1Password's built-in categories use these:

001  Login            100  Software License    108  Social Security Number
002  Credit Card      101  Bank Account        109  Wireless Router
003  Secure Note      102  Database            110  Server
004  Identity         103  Driver License      111  Email Account
005  Password         104  Outdoor License     112  API Credential
006  Document         105  Membership          113  Medical Record
                      106  Passport            114  SSH Key
                      107  Reward Program      115  Crypto Wallet

The numbers run in two blocks, 001 to 006 and then 100 upward, and the list grows. The newest, Crypto Wallet at 115, is missing from Bitwarden's own 1PUX importer. Treat an unrecognized id as a reason to read the item generically, never to skip it. Every category uses the same sections-and-fields shape underneath, and an item type nobody has mapped still imports with its values and labels intact.

Custom fields

1Password items carry arbitrary extra fields grouped into sections, and in a 1PUX those keep their meaning. A concealed value stays concealed, a multi-line field stays a note, and an attached file stays a file.

The one lossy case is an address, which collapses from its separate street, city, state, postal code and country parts into a single joined text field.

Attachments

Attachments reach a 1PUX by two different routes. A file attached to a section appears as a field whose value is a file object. A Document item, category 006, has no such section: its documentAttributes hangs directly off the item.

"details": {
  "sections": [],
  "documentAttributes": {
    "fileName": "contract.pdf",
    "documentId": "kzbq4m7xrh2ptnv6ljec3wsdfa",
    "decryptedSize": 4670
  }
}

Both point at a file under files/, named documentId__filename. An importer that only walks sections finds the first kind and silently drops the second, leaving the document as an entry with a title and nothing else. Nothing reports the loss, because the item itself still imports.

The files/ directory

Each vault's avatar is in there too, named <id>.png with no __ separator, and referenced from vault.attrs.avatar instead of from any item. Anything matching files to items by splitting on __ skips them, which is correct, if by accident.

Password history

Login items carry a passwordHistory array, and each entry is a value plus a time in epoch seconds:

"passwordHistory": [
  { "value": "the oldest one",  "time": 1760000100 },
  { "value": "then this one",   "time": 1760000200 },
  { "value": "most recent old", "time": 1760000300 }
]

The array is ordered oldest first, the reverse of Bitwarden's. Anything that truncates it to a fixed number of past values keeps the wrong end unless it reverses the array first.

time records when a value stopped being current, not when it was set: the last entry's time is exactly the item's own updatedAt.

Passkeys

1Password stores a passkey on the login it belongs to, not as an item of its own. The login imports into Buddy; the passkey stays behind.

1Password metadata

Every item's overview carries a layer of 1Password's own bookkeeping: ps (a password strength score), subtitle, icons, locations, b5UserUuid, pbe, pgrng and watchtowerExclusions. None of it means anything outside 1Password, and neither does favIndex, which marks a favorite.

The two to keep are createdAt and updatedAt, which let an imported entry keep its real age instead of looking like you created it today.

CSV format

Nine flat columns, and only Login items get a row. Cards, identities, secure notes, SSH keys and documents never reach the file, not even as a stripped-down row, and the file itself gives no sign that they were left out.

Title,Url,Username,Password,OTPAuth,Favorite,Archived,Tags,Notes
GitHub,https://github.com/login,octocat,correct-horse-battery,otpauth://totp/GitHub:octocat?secret=JBSWY3DPEHPK3PXP&issuer=GitHub,true,false,work,Personal account

What does survive is better than most CSV exports manage. Tags have a real column, and the TOTP secret comes out as a full URI with its settings intact. An Archived flag carries the same state the 1PUX records, and an archived item arrives archived through either file. Favorite sits alongside it and is dropped, the same as favIndex in the archive.

Everything in the sections of a 1PUX is gone here. There is one notes column and no structure inside it, so a login that carried a concealed license key and a two-line address in custom fields arrives with neither.

Buddy field mapping

1PUX

Source field Serialized Target field Notes
overview.title Always Title
overview.url Conditional URL The primary address only. Every address on the item is in overview.urls, the primary among them, so reading url alone silently drops the rest.
overview.urls[] Conditional Custom fields (derived) The extra addresses, imported as custom URL fields the same way Bitwarden's extra URIs are. The primary is not duplicated into one.
details.loginFields[] username Conditional Username
details.loginFields[] password Conditional Password
details.password Conditional Password Only on a Password item, category 005, which has no login fields.
details.loginFields[] other Conditional Custom fields (derived) Other inputs from the form the login was saved from, with no designation key. Password-type ones import concealed; checkboxes are dropped.
details.notesPlain Conditional Note
overview.tags[] Conditional Tags
details.sections[].fields[] totp Conditional TOTP
details.sections[].fields[] Conditional Custom fields Concealed becomes a secret field, multi-line becomes a note field, address collapses into one joined text field.
details.documentAttributes Conditional Attachment Hangs off the item rather than off a section, which is how a Document item stores its file, so a walk that only reads sections misses it entirely.
details.passwordHistory[] Always Password history (derived) A value and a time in epoch seconds, where the time is the moment that value stopped being current: the last entry's time is the item's own updatedAt. Present but empty on most items.
createdAt / updatedAt Always Timestamps
card.brand Conditional Dropped Derived from the card number instead.
item.state Always Tags (derived) Only active and archived ever appear, and trashed items are in neither file. Archived items import as ordinary entries carrying an archived tag, because Buddy's only non-live state is trash and putting an archive there would set a 30-day fuse on data the user chose to keep.
vault.attrs.name Always Tags (derived) 1Password has no folders, so the vault is its only grouping and it becomes a tag. Only when the export holds more than one: tagging every entry personal in a single-vault export tells nobody anything.
item.favIndex Always Dropped
export.attributes timestamp Always Export date

CSV

Source field Target field Notes
Title Title
Url URL Only the entry's primary URL is exported.
Username Username
Password Password
OTPAuth TOTP
Favorite Dropped The CSV spelling of favIndex, and dropped for the same reason: nothing on the other side to carry it.
Archived Tags (derived) Carries true or false and becomes the same archived tag the 1PUX state does, so one vault imports the same way through either file.
Tags Tags
Notes Note Plain text. Custom fields from the item's sections are not written anywhere in this file.

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.