Bitwarden vs LastPass Migration Guide: Complete Technical Walkthrough

Migrating password managers requires careful handling of sensitive data. For developers and power users, the transition from LastPass to Bitwarden offers improved open-source transparency, self-hosting options, and better CLI tooling. This guide walks through the technical process using command-line tools for maximum control and automation.

Why Developers Choose Bitwarden Over LastPass

Several technical factors make Bitwarden the preferred choice for developers:

Preparing for Migration

Before starting, ensure you have:

  1. A Bitwarden account (free or premium)
  2. LastPass credentials with admin access to your vault
  3. Node.js installed (for Bitwarden CLI)
  4. jq or similar JSON processing tools
# Install Bitwarden CLI
npm install -g @bitwarden/cli

# Verify installation
bw --version

Exporting Data from LastPass

LastPass provides CSV export through their browser extension or CLI. For programmatic control, use the LastPass CLI:

# Install LastPass CLI (Linux/macOS)
brew install lastpass-cli  # macOS
# or
sudo apt install lpass    # Debian/Ubuntu

# Export vault to CSV
lpass export --format=csv > lastpass-export.csv

The CSV export includes:

Handling TOTP Seeds

LastPass exports TOTP codes as “One-Time Passwords” in the Extra field. You’ll need to extract these manually for Bitwarden’s TOTP support:

# Extract TOTP seeds using grep and sed
# TOTP secrets typically appear as base32 strings
grep -oP '(?<=TOTP: )[A-Z2-7]+=*' lastpass-export.csv > totp-seeds.txt

Importing into Bitwarden

Bitwarden’s CLI handles imports directly:

# Login to Bitwarden
bw login your@email.com

# Unlock vault (will prompt for master password)
bw unlock

# Import the LastPass CSV
# --format lastpasscsv tells Bitwarden how to parse the data
bw import --format lastpasscsv --file ./lastpass-export.csv

The import process maps LastPass fields to Bitwarden equivalents:

Migrating TOTP Authenticators

LastPass stores TOTP secrets in a separate format. For full migration:

Method 1: Manual Export via Browser Extension

  1. Open LastPass browser extension
  2. Navigate to Account Settings → Export
  3. Export “Export Generic CSV”
  4. Extract the “One-Time Password” column

Method 2: Using a Python Script

#!/usr/bin/env python3
import csv
import sys

def parse_totp_from_csv(input_file, output_file):
    """Extract TOTP secrets from LastPass export"""
    totp_entries = []
    
    with open(input_file, 'r', encoding='utf-8') as f:
        reader = csv.DictReader(f)
        for row in reader:
            extra = row.get('Extra', '')
            # Look for TOTP patterns in the notes
            if 'TOTP:' in extra or 'totp:' in extra.lower():
                # Parse and clean the secret
                for line in extra.split('\n'):
                    if 'TOTP' in line or 'totp' in line.lower():
                        parts = line.split(':')
                        if len(parts) >= 2:
                            secret = parts[-1].strip()
                            totp_entries.append({
                                'url': row['url'],
                                'name': row['name'],
                                'secret': secret
                            })
    
    # Output for manual TOTP entry
    with open(output_file, 'w') as f:
        for entry in totp_entries:
            f.write(f"{entry['name']}: {entry['secret']}\n")
    
    print(f"Found {len(totp_entries)} TOTP entries")
    return totp_entries

if __name__ == '__main__':
    parse_totp_from_csv('lastpass-export.csv', 'totp-seeds.txt')

Adding TOTP to Bitwarden

After migration, manually add TOTP to each login item:

# Get item ID
bw list items --url "github.com"

# Update with TOTP (requires premium for TOTP)
bw edit item <item-id> --totp "JBSWY3DPEHPK3PXP"

Bulk Operations with Bitwarden CLI

For large vaults, use scripting for efficiency:

#!/bin/bash
# Sync vault after import
bw sync

# List all items with specific tags
bw list items --search "" | jq '.[] | select(.organizationId == null)'

# Export Bitwarden vault for backup
bw export --format json --output ./bitwarden-backup.json

Folder Organization

LastPass uses folders; Bitwarden uses collections for organizations and folders for personal vaults. Import automatically creates folders:

# View imported folders
bw list folders

# Reorganize using CLI
bw move <item-id> <folder-name>

Verification Checklist

After migration, verify your data:

# Verify specific entry
bw get item "GitHub" | jq '{username, password, totp, notes}'

Automating Continuous Migration

For team migrations, script the process:

// migration-script.js
const { execSync } = require('child_process');

function migrateEntry(entry) {
  try {
    // Create item in Bitwarden
    const cmd = `bw create item --organization-id ${process.env.BW_ORG_ID}`;
    execSync(cmd, {
      input: JSON.stringify(entry),
      encoding: 'utf-8'
    });
    console.log(`Migrated: ${entry.name}`);
  } catch (err) {
    console.error(`Failed: ${entry.name}`, err.message);
  }
}

Security Considerations

During migration:

  1. Use a clean environment: Run on a secure machine without malware
  2. Encrypt exports: Store temporary files encrypted
  3. Delete intermediates: Remove CSV files after successful import
  4. Rotate passwords: Consider updating critical passwords post-migration
  5. Enable 2FA: Set up Bitwarden with TOTP or FIDO2
# Secure cleanup
shred -u lastpass-export.csv
shred -u totp-seeds.txt

Conclusion

Moving from LastPass to Bitwarden provides better control over your password infrastructure. The CLI-based migration described here gives developers precise control over every aspect of the transfer. While some manual TOTP handling is required, the process is repeatable and automatable.

For teams, consider running Bitwarden Vault as a Docker container for full data ownership:

docker run -d --name bitwarden \
  -e DATABASE_URL=postgresql://user:pass@db:5432/vault \
  -p 8080:80 \
  bitwarden/self-host:latest

Built by theluckystrike — More at zovo.one