Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save TheMeaner0/cb54486fc5748734a829a3181fa6e0bf to your computer and use it in GitHub Desktop.
Save TheMeaner0/cb54486fc5748734a829a3181fa6e0bf to your computer and use it in GitHub Desktop.
Proton Pass json export file -> KeePassXC import CSV
/*
* Fork of the original `proton_to_keepassxc.js` script by nikspyratos
* Original script: https://gist.github.com/nikspyratos/bd0b5ef05a4d82d2d0425cb4be9844db
*
* This fork fixed a bug with how Proton Pass stores usernames and emails in its JSON export.
* Proton Pass uses separate JSON tags for emails (`itemEmail`) and usernames (`itemUsername`).
* KeePassXC imports only the `itemUsername` field, which makes it so there might be missing data.
* the username is stored under the `itemEmail` tag instead.
*
* This fork fixes the bug in the original script by checking both tags and using one if the other is not available.
*
*/
#!/usr/bin/env node
const fs = require('fs');
function convertProtonPassToJson(protonPassJson) {
// Parse the JSON input
const data = JSON.parse(protonPassJson);
// Define an array to hold CSV lines
let csvLines = [];
// CSV header line
csvLines.push("Group,Title,Username,Password,URL,Notes,TOTP,Icon,Last Modified,Created");
// Process each vault
Object.values(data.vaults).forEach(vault => {
// Skip the vault if its name is "Recycle Bin"
if (vault.name === "Recycle Bin") {
return;
}
// Process each item in the vault
vault.items?.forEach(item => {
const itemData = item.data.content;
const modifiedTime = item.modifyTime ? new Date(item.modifyTime * 1000).toISOString() : '';
const createdTime = item.createTime ? new Date(item.createTime * 1000).toISOString() : '';
// Determine the username (use 'itemUsername' or fall back to 'itemEmail')
const username = itemData?.itemUsername || itemData?.itemEmail || '';
// Escaping newlines in notes and special characters
const notesEscaped = item.data.metadata?.note?.replace(/\n/g, '\\n').replace(/"/g, '\\"') || '';
const passwordEscaped = itemData?.password?.replace(/\\/g, '\\\\').replace(/"/g, '\\"') || '';
const line = [
`"${vault.name}"`,
`"${item.data.metadata?.name || ''}"`,
`"${username}"`,
`"${passwordEscaped}"`,
`"${itemData?.urls?.join(', ') || ''}"`,
`"${notesEscaped}"`,
`"${itemData?.totpUri || ''}"`,
`""`, // Icon field is left blank as it is not in the JSON
`"${modifiedTime}"`,
`"${createdTime}"`
].join(',');
csvLines.push(line);
});
});
// Join all lines to create CSV text
return csvLines.join('\n');
}
// Get the file path from command line arguments
const inputFilePath = process.argv[2];
const outputFilePath = process.argv[3];
if (!inputFilePath || !outputFilePath) {
console.error("Please provide an input file path and an output file path.");
process.exit(1);
}
const protonPassJson = fs.readFileSync(inputFilePath, 'utf8');
const csvData = convertProtonPassToJson(protonPassJson);
fs.writeFileSync(outputFilePath, csvData);
console.log(`CSV data written to ${outputFilePath}`);
@TheMeaner0
Copy link
Author

TheMeaner0 commented Dec 7, 2024

Usage:

./protonpass_to_keepassxc_csv.js {JSON_export} {csv_output}

OR

node protonpass_to_keepassxc_csv.js {JSON_export} {csv_output}

This will output a CSV of your ProtonPass export that you can use for KeePassXC imports and potentially others (unsure, have not tested other password managers).

You will need nodejs installed on your system.

Fork of the original proton_to_keepassxc.js script by nikspyratos
Original script: https://gist.github.com/nikspyratos/bd0b5ef05a4d82d2d0425cb4be9844db

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment