Skip to content

Instantly share code, notes, and snippets.

@talk2bryan
Last active March 3, 2025 20:01
Show Gist options
  • Save talk2bryan/d6e1f9cf960a9a88c6e85db98f509dee to your computer and use it in GitHub Desktop.
Save talk2bryan/d6e1f9cf960a9a88c6e85db98f509dee to your computer and use it in GitHub Desktop.
KeePassXC CSV export file to ProtonPass Generic CSV import file
# Usage: python keepassxc_to_protonpass_import.py
#
# Description: This script converts a KeePassXC CSV export to a ProtonPass
# Generic CSV import.
#
# The script assumes that the KeePassXC CSV file has the following headers:
# Group, Title, Username, Password, URL, Notes, TOTP, Icon, Last Modified, Created
#
# The script assumes that the ProtonPass CSV file has the following headers:
# name, url, email, username, password, note, totp, vault
#
import csv
PROTONPASS_HEADERS = [
"name",
"url",
"email",
"username",
"password",
"note",
"totp",
"vault",
]
KEEPASSXC_HEADERS = [
"Group",
"Title",
"Username",
"Password",
"URL",
"Notes",
"TOTP",
"Icon",
"Last Modified",
"Created",
]
def map_keepassxc_to_protonpass(keepassxc_row: dict) -> dict:
"""Converts a KeePassXC row to a ProtonPass row.
Args:
keepassxc_row (dict): A row from a KeePassXC CSV file.
Returns:
dict: A row corresponding to a ProtonPass CSV file.
"""
protonpass_row = {
"name": keepassxc_row["Title"],
"url": keepassxc_row["URL"],
"email": keepassxc_row["Username"] if "@" in keepassxc_row["Username"] else "",
"username": keepassxc_row["Username"],
"password": keepassxc_row["Password"],
"note": keepassxc_row["Notes"],
"totp": keepassxc_row["TOTP"],
"vault": keepassxc_row["Group"],
}
return protonpass_row
def convert_keepassxc_to_protonpass(input_filepath: str, output_filepath: str) -> None:
"""Converts a KeePassXC CSV export to a ProtonPass Generic CSV import."""
with open(input_filepath, mode="r", newline="", encoding="utf-8") as infile, open(
output_filepath, mode="w", newline="", encoding="utf-8"
) as outfile:
reader = csv.DictReader(
infile,
quotechar='"',
delimiter=",",
quoting=csv.QUOTE_ALL,
skipinitialspace=True,
)
writer = csv.DictWriter(
outfile,
fieldnames=PROTONPASS_HEADERS,
quotechar='"',
delimiter=",",
quoting=csv.QUOTE_ALL,
)
writer.writeheader()
for row in reader:
# Ignore rows with Group "Recycle Bin"
# Important! - Comment out the following lines if you want to include deleted entries
# if row["Group"] == "Recycle Bin":
# continue
# Remove "Root/" from the group name
if row["Group"].startswith("Root/"):
row["Group"] = row["Group"][5:]
protonpass_row = map_keepassxc_to_protonpass(row)
writer.writerow(protonpass_row)
# Example usage
INPUT_FILE = "/home/username/keepassxc.csv"
OUTPUT_FILE = "/home/username/protonpass.csv"
convert_keepassxc_to_protonpass(input_filepath=INPUT_FILE, output_filepath=OUTPUT_FILE)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment