Complete Python implementation of LastPass CLI with API
Project description
lastpass-py
A complete Python implementation of the LastPass CLI with a friendly API for programmatic access to your LastPass vault.
Features
- ๐ Secure - AES-256 encryption, PBKDF2 key derivation
- ๐ Pure Python - No binary dependencies, works everywhere
- ๐ Complete CLI - All major LastPass commands implemented
- ๐ Python API - Clean interface for scripts and automation
- ๐งช Well Tested - 331+ tests with 95% code coverage
- ๐ Cross-Platform - Linux, macOS, and Windows
Table of Contents
Installation
From PyPI
pip install lastpass-py
From Source
git clone https://github.com/dynacylabs/lastpass-py.git
cd lastpass-py
pip install -e .
Development Install
pip install -e ".[dev]"
This installs additional tools: pytest, pytest-cov, pytest-mock, responses
Optional: Clipboard Support
pip install pyperclip
Quick Start
Command Line
# Login
lpass login user@example.com
# List accounts
lpass ls
# Show account details
lpass show github --password
# Generate password
lpass generate 20
# Logout
lpass logout
Python API
from lastpass import LastPassClient
# Login
client = LastPassClient()
client.login("user@example.com", "password")
# Get accounts
accounts = client.get_accounts()
for account in accounts:
print(f"{account.name}: {account.username}")
# Find specific account
github = client.find_account("github")
print(github.password)
# Generate password
password = client.generate_password(length=20)
# Logout
client.logout()
CLI Reference
Commands
| Command | Description |
|---|---|
lpass login [USERNAME] |
Login to LastPass |
lpass logout |
Logout and clear session |
lpass status |
Show login status |
lpass show [QUERY] |
Display account details |
lpass ls [GROUP] |
List accounts |
lpass generate [LENGTH] |
Generate password |
lpass sync |
Sync vault from server |
lpass add [NAME] |
Add new account |
lpass edit [QUERY] |
Edit existing account |
lpass rm [QUERY] |
Remove account |
lpass duplicate [QUERY] |
Duplicate account |
lpass mv [QUERY] [GROUP] |
Move account to group |
Common Options
login
lpass login user@example.com --trust --otp 123456
--trust- Trust this device--otp CODE- One-time password for 2FA--force- Force new login
show
lpass show github --password --clip
--password- Show only password--username- Show only username--url- Show only URL--notes- Show only notes--field NAME- Show specific field--json- Output as JSON--clip- Copy to clipboard
ls
lpass ls Work --long --json
--long- Long listing format--json- Output as JSON
generate
lpass generate 24 --no-symbols --clip
--no-symbols- Exclude special characters--clip- Copy to clipboard
add
lpass add "GitHub" --username user@example.com --url https://github.com
--username- Account username--password- Account password (prompts if not provided)--url- Website URL--notes- Account notes--group- Group/folder name--generate LENGTH- Generate password of specified length
edit
lpass edit "GitHub" --password --url https://github.com/login
--name- Update account name--username- Update username--password- Update password (prompts if flag provided without value)--url- Update URL--notes- Update notes--group- Move to different group
rm
lpass rm "Old Account" --force
--force- Skip confirmation prompt
duplicate
lpass duplicate "GitHub" --name "GitHub Backup"
--name- Name for duplicate (defaults to "Copy of [original]")
mv
lpass mv "GitHub" "Work/Development"
- Moves account to specified group/folder
API Reference
LastPassClient
from lastpass import LastPassClient
client = LastPassClient(server="lastpass.com", config_dir=None)
Authentication
login(username, password=None, trust=False, otp=None, force=False)
Login to LastPass. Returns Session object.
client.login("user@example.com", "password", otp="123456")
logout(force=False)
Logout and clear session data.
client.logout()
is_logged_in()
Check if currently logged in. Returns bool.
if client.is_logged_in():
print("Logged in!")
Vault Operations
get_accounts(sync=True)
Get all accounts. Returns List[Account].
accounts = client.get_accounts()
find_account(query, sync=True)
Find account by name, ID, or URL. Returns Account or None.
account = client.find_account("github")
search_accounts(query, sync=True, group=None)
Search accounts by keyword. Returns List[Account].
matches = client.search_accounts("google")
list_groups(sync=True)
Get all group/folder names. Returns List[str].
groups = client.list_groups()
sync(force=False)
Sync vault from server.
client.sync(force=True)
Utilities
generate_password(length=16, symbols=True)
Generate random password. Returns str.
password = client.generate_password(length=20, symbols=False)
get_password(query, sync=True)
Get password for account. Returns str or None.
password = client.get_password("github")
get_username(query, sync=True)
Get username for account. Returns str or None.
get_notes(query, sync=True)
Get notes for account. Returns str or None.
Write Operations
add_account(name, username="", password="", url="", notes="", group="", fields=None)
Add new account to vault. Returns account ID as str.
account_id = client.add_account(
name="GitHub",
username="user@example.com",
password="secret123",
url="https://github.com",
group="Work"
)
update_account(query, name=None, username=None, password=None, url=None, notes=None, group=None)
Update existing account. Only provided fields are updated.
client.update_account("GitHub", password="newsecret", url="https://github.com/login")
delete_account(query)
Delete account from vault.
client.delete_account("Old Account")
duplicate_account(query, new_name=None)
Duplicate an account. Returns new account ID as str.
new_id = client.duplicate_account("GitHub", "GitHub Backup")
move_account(query, new_group)
Move account to different group/folder.
client.move_account("GitHub", "Work/Development")
Data Models
Account
@dataclass
class Account:
id: str
name: str
username: str
password: str
url: str
group: str
notes: str
fullname: str
fields: List[Field]
attachments: List[Attachment]
share: Optional[Share]
def to_dict(self) -> Dict
def get_field(self, name: str) -> Optional[Field]
def is_secure_note(self) -> bool
Field
@dataclass
class Field:
name: str
value: str
type: str
checked: bool
Share
@dataclass
class Share:
id: str
name: str
readonly: bool
Exceptions
All exceptions inherit from LastPassException:
LoginFailedException- Authentication failedInvalidSessionException- Session expiredNetworkException- Network/HTTP errorDecryptionException- Decryption failedAccountNotFoundException- Account not foundInvalidPasswordException- Invalid password
from lastpass import LastPassClient, LoginFailedException
try:
client.login("user@example.com", "wrong")
except LoginFailedException:
print("Invalid credentials")
- Make your changes
- Add tests if applicable
- Submit a pull request
License
This project is licensed under the GNU General Public License v2.0 or later (GPLv2+), the same license as the original LastPass CLI.
Disclaimer
This is an independent implementation. It is not officially supported by LastPass/LogMeIn. Use at your own risk.
Implementation Details
Core Features Implemented
โ Cryptography
- AES-256-CBC encryption/decryption
- PBKDF2-HMAC-SHA256 key derivation
- RSA encryption for shared folders
- Base64 encoding/decoding
- SHA256 hashing
โ Authentication
- Username/password login
- Two-factor authentication (OTP)
- Session management
- Encrypted session storage
- Logout functionality
โ Vault Operations
- Download and parse encrypted blob
- Account listing and filtering
- Account search (by name, username, URL, ID)
- Group/folder listing
- Custom field support
- Shared folder support
โ CLI Commands
login- Login to LastPasslogout- Logout from LastPassstatus- Show login statusshow- Display account detailsls- List accountsgenerate- Generate random passwordsync- Sync vault from server
โ Python API
Complete programmatic access to LastPass functionality:
LastPassClient- Main client classlogin()/logout()- Authenticationget_accounts()- Get all accountsfind_account()- Find specific accountsearch_accounts()- Search vaultlist_groups()- Get folder listgenerate_password()- Generate passwordget_password()/get_username()/get_notes()- Convenience methods
Comparison with C CLI
This Python implementation provides:
โ All core functionality of the C-based CLI โ Python API for programmatic access โ No compilation required โ Easier to modify and extend โ Better error messages and debugging
Some differences:
- Clipboard support requires
pyperclipor system tools - Agent/daemon not implemented (use session-based auth)
- Some advanced features (shares management, etc.) are simplified
Security Notes
- Master Password: Never stored, only used for key derivation
- Encryption: AES-256-CBC with unique IVs
- Key Derivation: PBKDF2-HMAC-SHA256
- Session Storage: Encrypted with derived key, mode 0600
- Memory: Sensitive data cleared when possible
Configuration
Configuration is stored in:
- Linux/macOS:
~/.config/lpass/ - Windows:
%APPDATA%\lpass\
Files:
session: Encrypted session data
Testing
Running Tests
Quick start:
# Install dev dependencies
pip install -e ".[dev]"
# Run all tests
pytest
# With coverage
pytest --cov=lastpass --cov-report=term-missing
Test Modes
1. Mock Tests (Default)
Fast, offline tests using mocked API responses. No credentials needed.
pytest # Run all mock tests
pytest -v # Verbose output
pytest tests/test_client.py # Specific test file
2. Live API Tests
Tests against real LastPass API. Use a test account!
pytest --live --username test@example.com --password testpass
If email verification is required:
pytest --live --username test@example.com --password testpass --otp 123456
3. Complete Test Suite
Run both mock and live tests for full coverage:
pytest tests/ --live --username test@example.com --password testpass --cov=lastpass
Expected: 331+ tests passed, 95% coverage
Test Structure
tests/test_cli.py- CLI interface (87 tests)tests/test_client.py- Client API (42 tests)tests/test_cipher.py- Cryptography (26 tests)tests/test_models.py- Data models (16 tests)tests/test_http.py- HTTP client (26 tests)- And 8 more test files...
Coverage Report
Current coverage: 95%
Module Coverage
--------------------------------
lastpass/__init__.py 100%
lastpass/cli.py 99%
lastpass/http.py 96%
lastpass/cipher.py 96%
lastpass/models.py 95%
lastpass/client.py 93%
lastpass/session.py 93%
lastpass/blob.py 89%
--------------------------------
TOTAL 95%
Contributing
We welcome contributions! Here's how to get started:
Development Setup
-
Fork and clone
git clone https://github.com/YOUR_USERNAME/lastpass-py.git cd lastpass-py
-
Install dev dependencies
pip install -e ".[dev]"
-
Create a branch
git checkout -b feature/your-feature-name
Guidelines
Code Quality
- Follow PEP 8 style guidelines
- Add type hints to new functions
- Document public APIs with docstrings
- Keep functions focused and testable
Testing Requirements โ ๏ธ
- All tests must pass - Run
pytestbefore submitting - Maintain 95% coverage - Add tests for new code
- Include both unit and integration tests when applicable
# Verify before submitting
pytest --cov=lastpass --cov-report=term-missing
# Expected output:
# ========== 279 passed in X.XXs ==========
# TOTAL coverage: 95%
Commit Messages
- Use clear, descriptive commit messages
- Reference issue numbers when applicable
- Example:
fix: handle rate limiting in HTTP client (#123)
Submitting Changes
-
Run tests
pytest --cov=lastpass
Ensure: โ All tests pass โ Coverage โฅ 95%
-
Push your branch
git push origin feature/your-feature-name
-
Open a Pull Request
- Describe your changes clearly
- Reference any related issues
- Include test results/coverage report
Areas for Contribution
- ๐ Bug fixes and improvements
- ๐ Documentation enhancements
- ๐งช Additional test coverage
- โจ New features (discuss in an issue first)
- ๐ง Code refactoring
- ๐ Platform compatibility
Getting Help
- ๐ Check existing documentation
- ๐ฌ Open an issue for discussion
- ๐ Search closed issues for similar problems
Code of Conduct
- Be respectful and inclusive
- Welcome newcomers
- Focus on constructive feedback
- Assume good intentions
Comparison with LastPass CLI (C Implementation)
โ Implemented Features
This Python implementation now covers all major operations from the C CLI:
| Feature | C CLI | Python | Status |
|---|---|---|---|
| Authentication | |||
| Login with username/password | โ | โ | Full support |
| Two-factor auth (OTP) | โ | โ | Full support |
| Trust device | โ | โ | Full support |
| Logout | โ | โ | Full support |
| Session management | โ | โ | Full support |
| Vault Operations | |||
List accounts (ls) |
โ | โ | Full support |
Show account (show) |
โ | โ | Full support |
| Search/filter accounts | โ | โ | Full support |
| Sync vault | โ | โ | Full support |
Password generation (generate) |
โ | โ | Full support |
| Status check | โ | โ | Full support |
| Write Operations | |||
Add account (add) |
โ | โ | Full support |
Edit account (edit) |
โ | โ | Full support |
Delete account (rm) |
โ | โ | Full support |
Move account (mv) |
โ | โ | Full support |
Duplicate account (duplicate) |
โ | โ | Full support |
| Data Access | |||
| Account fields | โ | โ | Full support |
| Custom fields | โ | โ | Full support |
| Secure notes | โ | โ | Full support |
| Shared folders | โ | โ | Full support |
| Groups/folders | โ | โ | Full support |
| Cryptography | |||
| AES-256-CBC encryption | โ | โ | Full support |
| PBKDF2 key derivation | โ | โ | Full support |
| RSA for shared folders | โ | โ | Full support |
| Output Formats | |||
| Standard text output | โ | โ | Full support |
| Long listing format | โ | โ | Full support |
| JSON output | โ | โ | Full support |
| Clipboard support | โ | โ | Full support |
โ Not Implemented
The following advanced features from the C CLI are not implemented:
| Feature | C CLI | Python | Notes |
|---|---|---|---|
Change master password (passwd) |
โ | โ | High risk operation |
| Share management | โ | โ | Complex, requires share API |
| Import accounts | โ | โ | CSV import not implemented |
| Export accounts | โ | โ | Partial (JSON only, no CSV) |
| Attachments download | โ | โ | API exists, not in CLI |
| Agent/daemon mode | โ | โ | Not planned |
๐ฏ Design Philosophy
Python Implementation Focus:
- โ Complete CRUD operations - Create, Read, Update, Delete accounts
- โ Safe vault management - All standard operations supported
- โ Automation-friendly - Clean Python API for scripts
- โ Cross-platform - Pure Python, no compilation needed
- โ Well-tested - Comprehensive test coverage
Excluded Operations:
- Master password changes (use web app for security)
- Advanced share management (complex API)
- CSV import/export (JSON supported)
- Agent mode (session-based auth is simpler)
๐ Feature Coverage Summary
Core Functionality: 100% โ
Read Operations: 100% โ
Write Operations: 100% โ
(add, edit, delete, move, duplicate)
Advanced Features: 30% โ ๏ธ (passwd, shares, import not implemented)
Cryptography: 100% โ
Authentication: 100% โ
Session Management: 100% โ
Test Coverage: 95% โ
๐ Python-Specific Advantages
Features only in the Python implementation:
- ๐ Native Python API - Use as a library in your Python projects
- ๐ฆ No compilation -
pip installand you're ready - ๐ง Easy to extend - Pure Python, modify for your needs
- ๐งช Comprehensive tests - 331+ tests vs minimal C tests
- ๐ Better documentation - Docstrings, type hints, examples
- ๐ Modern architecture - Uses
requests, dataclasses, type hints
๐ก Use Cases
Perfect for:
- โ Retrieving passwords in automation scripts
- โ Integration with deployment pipelines
- โ Password lookups in Python applications
- โ Auditing vault contents
- โ Bulk password exports
- โ Cross-platform password access
Not suitable for:
- โ Creating/modifying vault entries (use web app)
- โ Account management workflows
- โ Complex share management
- โ Import/migration operations
๐ฎ Future Considerations
If there's demand, write operations could be added:
add- Create new accountsedit- Modify existing accountsrm- Delete accountsimport- Import from CSV
However, the current focus is on rock-solid read operations with excellent test coverage.
License
This project is licensed under the GNU General Public License v2.0 or later (GPLv2+).
See LICENSE for full details.
Security
- Master Password: Never stored or logged
- Encryption: AES-256-CBC with PBKDF2-SHA256
- Session Data: Encrypted at rest (mode 0600)
- Memory Safety: Sensitive data cleared when possible
Acknowledgments
- Original LastPass CLI by LastPass
- Python implementation by the community
Disclaimer
This is an independent implementation and is not officially supported by LastPass/LogMeIn. Use at your own risk.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lastpass_py-1.0.1.tar.gz.
File metadata
- Download URL: lastpass_py-1.0.1.tar.gz
- Upload date:
- Size: 76.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b7160a0a752401f682ee9919ede50e185b4c348c3a9002dba8696b5099501ba6
|
|
| MD5 |
8038a6cd3cb6839ca6b8b6b6f47a5851
|
|
| BLAKE2b-256 |
0aac78dda384f1cdedc0005a3241d5e6e9c5f2eb139fc3c707760ad53ff83f73
|
Provenance
The following attestation bundles were made for lastpass_py-1.0.1.tar.gz:
Publisher:
publish-to-pypi.yml on dynacylabs/lastpass-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lastpass_py-1.0.1.tar.gz -
Subject digest:
b7160a0a752401f682ee9919ede50e185b4c348c3a9002dba8696b5099501ba6 - Sigstore transparency entry: 707658628
- Sigstore integration time:
-
Permalink:
dynacylabs/lastpass-py@bdde1e38969d2fee78ea9eb5bedef36326d1cf02 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/dynacylabs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@bdde1e38969d2fee78ea9eb5bedef36326d1cf02 -
Trigger Event:
release
-
Statement type:
File details
Details for the file lastpass_py-1.0.1-py3-none-any.whl.
File metadata
- Download URL: lastpass_py-1.0.1-py3-none-any.whl
- Upload date:
- Size: 70.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a5cc531177db95e1ee6dc5446fa73c55f6821f55418774bdecc0d2c3f40e3b05
|
|
| MD5 |
60814d6b9401caf19d8e2fcac19c8979
|
|
| BLAKE2b-256 |
33d25ac383b9afbf7980fc71c86a2ca1023d1b8274a0b4f4eca784e8eeed1bdb
|
Provenance
The following attestation bundles were made for lastpass_py-1.0.1-py3-none-any.whl:
Publisher:
publish-to-pypi.yml on dynacylabs/lastpass-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lastpass_py-1.0.1-py3-none-any.whl -
Subject digest:
a5cc531177db95e1ee6dc5446fa73c55f6821f55418774bdecc0d2c3f40e3b05 - Sigstore transparency entry: 707658632
- Sigstore integration time:
-
Permalink:
dynacylabs/lastpass-py@bdde1e38969d2fee78ea9eb5bedef36326d1cf02 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/dynacylabs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@bdde1e38969d2fee78ea9eb5bedef36326d1cf02 -
Trigger Event:
release
-
Statement type: