Last updated: March 16, 2026

Switching from Android to iPhone presents a unique challenge for password manager users. Unlike moving between devices of the same platform, cross-platform migration requires careful attention to export formats, encryption, and compatibility. This guide provides practical methods for power users and developers who want full control over their credential transfer.

Table of Contents

Prerequisites

Before you begin, make sure you have the following ready:

Step 1 - Understand the Cross-Platform Migration Challenge

Password managers store sensitive data in encrypted vaults. The encryption key typically derives from your master password, which means the vault itself remains portable across platforms, but the import/export mechanisms differ significantly between Android apps and their iOS counterparts.

Most password managers support standard export formats like CSV or encrypted JSON, but the devil lies in the details. Certain fields may not transfer correctly, and some exporters intentionally exclude TOTP seeds or secure notes for security reasons. Understanding these nuances prevents data loss during migration.

Step 2 - Method 1: Cloud Sync (Simplest Approach)

The easiest path involves using your password manager’s built-in cloud synchronization. If you already use 1Password, Bitwarden, or similar services with cross-platform support, simply install the iOS app and sign in.

Verify your vault is syncing before switching devices
For Bitwarden CLI:
bw sync

Check sync status
echo $?

Before factory resetting your Android device, confirm that all items appear in the web vault or another trusted device. This verification step takes seconds but prevents hours of recovery work.

For developers, cloud sync provides the most reliable experience because it handles encryption consistently across platforms. The major password managers all support this workflow, though some require paid subscriptions for mobile sync.

Step 3 - Method 2: Encrypted Export/Import

When cloud sync isn’t available, or you prefer manual control, exporting your vault directly offers maximum transparency. This method works across all password managers that support encrypted exports.

Bitwarden Export

Bitwarden provides both unencrypted CSV and encrypted JSON exports. For security, prefer the encrypted format:

Install Bitwarden CLI
brew install bitwarden-cli

Login programmatically (will prompt for master password)
bw login your@email.com

Unlock vault and capture session key
export BW_SESSION=$(bw unlock --raw)

Export as encrypted JSON (includes TOTP seeds)
bw export --output ./vault-export.json --format json --encrypted

The encrypted export requires your master password to decrypt, making it safe for temporary storage on a computer. Transfer the file to your iPhone via AirDrop, iCloud, or USB, then import using the Bitwarden iOS app.

1Password Export

1Password’s command-line tool provides similar functionality:

Install 1Password CLI
brew install --cask 1password-cli

Sign in (opens browser for authentication)
op signin

Export vault items
op export --format json --vaults Personal > 1password-export.json

1Password’s export includes all item types but requires the 1Password subscription for CLI access. The exported JSON maintains field relationships that some CSV conversions lose.

Step 4 - Method 3: CSV Migration (Universal Compatibility)

For maximum compatibility, CSV exports work across nearly all password managers. However, CSV strips encryption and may lose custom fields.

Convert Bitwarden CSV to 1Password CSV format
Original Bitwarden format:
login_uri,login_username,login_password,login_totp,name,notes,...

Create import-ready CSV with required fields
awk -F',' 'NR>1 {print $1","$2","$3","$5}' bitwarden-export.csv > import-ready.csv

This approach requires field mapping between exporters and importers. Most password managers accept CSV with columns like url, username, password, totp, note, and name. Test with a small subset before migrating your entire vault.

Step 5 - Handling TOTP Seeds During Migration

Time-based one-time passwords (TOTP) present a specific challenge. Many export tools exclude these by default, requiring explicit opt-in:

Bitwarden CLI - Include TOTP in export
bw export --format json --include-totp

For 1Password - TOTP seeds export with items
op export --include-otp

If your password manager doesn’t export TOTP seeds, you’ll need to manually transfer each 2FA code by scanning the QR code again. This process becomes tedious with dozens of accounts but remains necessary for full credential access on your new device.

Step 6 - Android-Specific Export Steps

On Android, most password managers store exports in app-specific directories. Access these through Android’s file manager:

  1. Open your password manager app
  2. Navigate to Settings → Export
  3. Choose format (encrypted JSON preferred)
  4. Save to a location accessible by Files app or Google Drive
  5. Transfer to your computer or directly to iPhone

For Bitwarden Android app, the export appears in /Download/Bitwarden/ by default. Use Android’s share functionality to send the file to yourself via email or cloud storage.

Step 7 - iOS Import Process

Once your export file reaches iPhone, import through the password manager’s settings:

  1. Install the password manager from App Store
  2. Sign in to your account (if using cloud sync) or select “Import”
  3. Choose the import source (file or cloud storage)
  4. Select your exported file
  5. Confirm field mapping if prompted
  6. Wait for import completion, large vaults take several minutes
Verify import success via CLI
bw list items | jq 'length'  # Count items in vault

Compare the count against your original vault to ensure complete transfer.

Step 8 - Command-Line Automation for Developers

For developers managing multiple accounts or performing migrations frequently, CLI automation reduces repetition:

#!/bin/bash
migrate-password-vault.sh

EMAIL="$1"
OUTPUT_DIR="$2"

Install dependencies
brew install bitwarden-cli

Interactive login (safer than embedding credentials)
echo "Logging into Bitwarden..."
bw login "$EMAIL"

Unlock and export
export BW_SESSION=$(bw unlock --raw)
bw export --output "$OUTPUT_DIR/vault.json" --format json --encrypted

Create backup with timestamp
cp "$OUTPUT_DIR/vault.json" "$OUTPUT_DIR/vault-$(date +%Y%m%d).json"

echo "Export complete: $OUTPUT_DIR/vault.json"

This script creates timestamped backups, useful for audit trails or rollback capability. Run it on your Android device before switching, then copy exports to your iPhone.

Security Considerations During Migration

Throughout the migration process, maintain these security practices:

Troubleshooting Common Issues

Import fails with field mapping error: CSV column order matters. Check your password manager’s required format and reorder columns accordingly.

TOTP codes don’t work after import: Ensure your iPhone’s time settings sync automatically. TOTP relies on precise time alignment.

Missing items after import - Some password managers exclude archived or trashed items by default. Check these folders in your original vault before deletion.

Large vault import timeout - iOS may kill the app during long imports. Split large exports into smaller batches or use desktop import when available.

Advanced Migration Scenarios

Migrating Between Different Password Managers

Cross-platform migrations (Bitwarden to 1Password, etc.) present additional complexity:

#!/bin/bash
Convert between password manager formats

Bitwarden CSV to 1Password CSV
convert_bitwarden_to_1password() {
  local input_file="$1"
  local output_file="$2"

  # Bitwarden columns: folder,favorite,type,name,notes,fields,login_uri,login_username,login_password,login_totp
  # 1Password columns: title,url,username,password,notes

  awk -F',' 'NR>1 {
    # Extract relevant fields
    name=$4
    url=$7
    username=$8
    password=$9
    notes=$5

    # Output in 1Password format
    printf "\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n", name, url, username, password, notes
  }' "$input_file" > "$output_file"

  echo "Converted $input_file to 1Password format: $output_file"
}

convert_bitwarden_to_1password "bitwarden-export.csv" "1password-import.csv"

Handling Sub-passwords and Security Questions

Some password managers store additional security data that CSV doesn’t capture:

{
  "entry": {
    "name": "Bank Account",
    "password": "MainPassword123!",
    "security_questions": [
      {
        "question": "What was your first pet's name?",
        "answer": "Fluffy"
      }
    ],
    "additional_fields": {
      "account_number": "xxxx-xxxx-1234",
      "branch_code": "NYC001"
    }
  }
}

Export to JSON format (not CSV) to preserve this metadata:

Bitwarden - Export with all metadata
bw export --format json --output vault-complete.json

Verify all security questions included
jq '.items[].securityQuestions' vault-complete.json | grep -c "question"

Synchronization Verification Protocol

After migration, verify completeness:

#!/bin/bash
verify-migration.sh

source_app="$1"
target_app="$2"

Count entries in source
source_count=$(bw list items | jq 'length')

Wait for target to sync
echo "Waiting 60 seconds for sync..."
sleep 60

Count entries in target
target_count=$(op list items | jq 'length')

if [ "$source_count" -eq "$target_count" ]; then
  echo " Migration verified: $source_count items in both vaults"
else
  echo " Migration incomplete"
  echo "  Source: $source_count items"
  echo "  Target: $target_count items"
  echo "  Missing: $((source_count - target_count))"
fi

Step 9 - Emergency Recovery from Migration Failure

If migration fails partway through, recovery requires careful sequencing:

Step 1 - Restore from backup (if available)
restore_from_backup() {
  local backup_file="$1"
  local backup_date=$(date -r "$backup_file" '+%Y-%m-%d')

  echo "Restoring from backup dated $backup_date"

  # Decrypt backup if encrypted
  if [[ "$backup_file" == *.gpg ]]; then
    gpg --decrypt "$backup_file" > vault-restored.json
  else
    cp "$backup_file" vault-restored.json
  fi

  # Import into target manager
  echo "Importing into target password manager..."
}

Step 2 - Verify recovery
verify_recovery() {
  # Check for data corruption
  jq . vault-restored.json > /dev/null
  if [ $? -ne 0 ]; then
    echo "ERROR: Backup file is corrupted"
    return 1
  fi

  # Count items
  local item_count=$(jq '.items | length' vault-restored.json)
  echo "Recovered $item_count items"
  return 0
}

restore_from_backup "vault-backup-2026-03-20.json.gpg"
verify_recovery

Step 10 - Device-Specific Migration Quirks

Android Quirks

iOS Quirks

Step 11 - Security Practices Throughout Migration

Maintain these practices during the transition:

#!/bin/bash
migration-security-checklist.sh

1. Backup original vault before any export
cp ~/.password-manager/vault.db vault-backup-$(date +%s).db
gpg --symmetric vault-backup-*.db

2. Verify backup integrity
gpg vault-backup-*.db.gpg --output - | md5sum

3. Generate secure temporary passwords
(Use these during transition if accounts need password reset)

4. Document migration in audit log
echo "[$(date)] Password manager migration started" >> migration.log

5. Securely delete original exports after verification
shred -vfz -n 7 bitwarden-export.json  # 7-pass overwrite

6. Verify new manager accepts all accounts
Test login to 5 random accounts to confirm import worked

7. Update emergency access contacts
(If your password manager has emergency access sharing)

Step 12 - Post-Migration: Ongoing Verification

After successful migration, continue verifying integrity:

#!/bin/bash
monthly-vault-audit.sh

Run monthly to catch issues early
if [ "$(date +%d)" == "15" ]; then
  # Compare vault count to baseline
  current_count=$(bw list items | jq 'length')
  baseline_count=347  # Your baseline count

  if [ "$current_count" -ne "$baseline_count" ]; then
    echo "WARNING: Vault size changed from $baseline_count to $current_count"
    bw list items | jq '.[] | {name, uri}' > vault-audit-$(date +%Y%m%d).json
  fi

  # Verify no corrupted entries
  bw list items | jq '.[] | select(.login.password | length < 8)' | wc -l > short-passwords.txt

  if [ $(cat short-passwords.txt) -gt 0 ]; then
    echo "WARNING: Found $(cat short-passwords.txt) entries with suspiciously short passwords"
  fi
fi

Frequently Asked Questions

How long does it take to handle password manager when switching phones?

For a straightforward setup, expect 30 minutes to 2 hours depending on your familiarity with the tools involved. Complex configurations with custom requirements may take longer. Having your credentials and environment ready before starting saves significant time.

What are the most common mistakes to avoid?

The most frequent issues are skipping prerequisite steps, using outdated package versions, and not reading error messages carefully. Follow the steps in order, verify each one works before moving on, and check the official documentation if something behaves unexpectedly.

Do I need prior experience to follow this guide?

Basic familiarity with the relevant tools and command line is helpful but not strictly required. Each step is explained with context. If you get stuck, the official documentation for each tool covers fundamentals that may fill in knowledge gaps.

Is this approach secure enough for production?

The patterns shown here follow standard practices, but production deployments need additional hardening. Add rate limiting, input validation, proper secret management, and monitoring before going live. Consider a security review if your application handles sensitive user data.

Where can I get help if I run into issues?

Start with the official documentation for each tool mentioned. Stack Overflow and GitHub Issues are good next steps for specific error messages. Community forums and Discord servers for the relevant tools often have active members who can help with setup problems.

Related Articles