#!/usr/bin/env python3
import json
import uuid
import argparse
def parse_otpauth_uri (uri):
parts = uri.split( '?' )
label = parts[ 0 ].split( '/' )[ - 1 ]
service, account = label.split( ':' , 1 ) if ':' in label else (label, '' )
return { 'service' : service, 'account' : account}
def convert_otpauth_to_bitwarden (input_file, output_file):
with open (input_file, 'r' , encoding = 'utf-8' ) as f:
uris = [line.strip() for line in f if line.strip().startswith( 'otpauth://' )]
items = []
for uri in uris:
parsed = parse_otpauth_uri(uri)
bw_item = {
"id" : str (uuid.uuid4()).upper(),
"type" : 1 ,
"name" : f " { parsed[ 'service' ] } " ,
"favorite" : False ,
"login" : {
"username" : parsed[ 'account' ],
"totp" : uri,
}
}
items.append(bw_item)
output = { "encrypted" : False , "items" : items}
with open (output_file, 'w' , encoding = 'utf-8' ) as f:
json.dump(output, f, indent = 2 , ensure_ascii = False )
print ( f "Converted { len (items) } items to { output_file } " )
if __name__ == "__main__" :
parser = argparse.ArgumentParser(description = "Convert otpauth URIs → Bitwarden JSON" )
parser.add_argument( "input" , help = "File with otpauth URIs" )
parser.add_argument( "-o" , "--output" , default = "bitwarden_export.json" )
args = parser.parse_args()
convert_otpauth_to_bitwarden(args.input, args.output)