A robust, feature-rich Python application for downloading photos and videos from Zenfolio galleries with advanced capabilities including resume functionality, concurrent downloads, interactive menus, batch processing, and comprehensive error handling.
- π Concurrent Downloads: Download multiple files simultaneously with configurable concurrency
- β―οΈ Resume Capability: Automatically resume interrupted downloads from where they left off
- π Intelligent Retry Logic: Exponential backoff retry mechanism for failed downloads
- π Progress Tracking: Real-time progress bars, detailed statistics, and checkpoint management
- ποΈ Cache System: Gallery hierarchy caching to minimize API calls and improve performance
- π‘οΈ Comprehensive Error Handling: Detailed error reporting, logging, and graceful failure recovery
- β File Integrity Verification: Optional verification of downloaded files
- π Timestamp Preservation: Maintain original file creation and modification timestamps
- π― Interactive Menu Mode: User-friendly menu system for browsing and selecting galleries
- β‘ Command-Line Interface: Full CLI with extensive options for automation and scripting
- π¦ Batch Processing: Download entire archives or specific folder collections
- π Advanced Filtering: Filter galleries by name patterns, IDs, or folder hierarchies
- π Retrieval Queue Management: Handle Zenfolio's retrieval queue for archived content
- ποΈ Metadata Export: Export complete gallery structure and metadata to JSON/CSV
- π§ Debug Tools: Comprehensive debugging utilities for troubleshooting
- βοΈ First-Time Setup: Guided configuration wizard for new users
- π Statistics & Analytics: Detailed download statistics and progress reporting
- π Shared Gallery Support: Download original-quality photos from shared gallery URLs (no login required)
# Clone the repository
git clone <repository-url>
cd zenfolio-downloader
# Create and activate virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txtRun the setup wizard to configure your credentials and preferences:
python main.py --setupOr manually create your configuration:
# Copy the sample environment file
cp .env.sample .env
# Edit .env with your Zenfolio credentials
nano .env # or your preferred editorpython main.pyLaunches an interactive menu where you can browse folders, select galleries, and manage downloads.
# Download all galleries
python main.py
# Download specific folder by ID
python main.py --folder-id 1234567890
# Download specific gallery by ID
python main.py --gallery-id 9876543210
# Download with custom settings
python main.py --concurrent-downloads 4 --output-dir ./my-photosThe application uses a comprehensive .env configuration file. All settings are documented in .env.sample:
ZENFOLIO_USERNAME=your_zenfolio_username
ZENFOLIO_PASSWORD=your_zenfolio_passwordCONCURRENT_DOWNLOADS=8 # Simultaneous downloads (1-20)
DEFAULT_OUTPUT_DIR=./downloads # Download destination
OVERWRITE_EXISTING=false # Overwrite existing filesMAX_RETRIES=5 # Maximum retry attempts (0-50)
INITIAL_BACKOFF_SECONDS=1.0 # Initial retry delay
MAX_BACKOFF_SECONDS=60.0 # Maximum retry delay
REQUEST_TIMEOUT=60 # API request timeout (5-300s)
DOWNLOAD_TIMEOUT=30 # File download timeout (10-300s)
CHUNK_SIZE=8192 # Download chunk size in bytesLOG_LEVEL=INFO # DEBUG, INFO, WARNING, ERROR, CRITICAL
LOG_FILE=zenfolio_downloader.log # Log file path (empty to disable)CACHE_ENABLED=true # Enable gallery hierarchy caching
CACHE_DIR=.zenfolio_cache # Cache directory path
CACHE_TTL_HOURS=48 # Cache expiration time (1-168 hours)VERIFY_INTEGRITY=true # Verify downloaded file integrity
PRESERVE_TIMESTAMPS=true # Maintain original file timestampszenfolio-downloader/
βββ π main.py # Main application entry point
βββ π requirements.txt # Python dependencies
βββ π .env.sample # Sample configuration file
βββ π .gitignore # Git ignore rules
βββ π api/ # Zenfolio API client and models
β βββ __init__.py
β βββ exceptions.py # API exception classes
β βββ models.py # Data models (Gallery, Group, etc.)
β βββ zenfolio_client.py # Main API client
βββ π auth/ # Authentication management
β βββ __init__.py
β βββ token_manager.py # Authentication token handling
β βββ zenfolio_auth.py # Zenfolio authentication logic
βββ π cache/ # Caching system
β βββ __init__.py
β βββ cache_manager.py # Gallery hierarchy caching
βββ π config/ # Configuration management
β βββ __init__.py
β βββ settings.py # Settings validation and loading
βββ π download/ # Download management
β βββ __init__.py
β βββ concurrent_downloader.py # Concurrent download handling
β βββ download_manager.py # Main download orchestration
β βββ integrity_checker.py # File integrity verification
β βββ retry_manager.py # Retry logic and backoff
βββ π filesystem/ # File system utilities
β βββ __init__.py
β βββ directory_manager.py # Directory creation and management
β βββ duplicate_detector.py # Duplicate file detection
β βββ file_manager.py # File operations and metadata
βββ π logs/ # Logging configuration
β βββ __init__.py
β βββ logger.py # Logging setup and configuration
βββ π progress/ # Progress tracking and checkpoints
β βββ __init__.py
β βββ checkpoint_manager.py # Download checkpoint management
β βββ console_progress.py # Console progress display
β βββ progress_tracker.py # Progress tracking utilities
β βββ retrieval_queue.py # Zenfolio retrieval queue handling
β βββ statistics.py # Download statistics tracking
βββ π utils/ # Utility functions
βββ __init__.py
βββ constants.py # Application constants
βββ first_time_setup.py # Initial setup wizard
βββ helpers.py # General utility functions
βββ interactive_menu.py # Interactive menu system
βββ metadata_exporter.py # Metadata export functionality
βββ shared_gallery.py # Shared gallery download support
# List all available galleries
python main.py --list-galleries
# List only folders/groups
python main.py --list-folders --folder-depth 2
# Show detailed gallery information
python main.py --list-galleries --list-details --show-ids
# Perform dry run (show what would be downloaded)
python main.py --dry-run
# Show download statistics without downloading
python main.py --stats-only# Download specific folder and all its contents
python main.py --folder-id 1234567890
# Download specific gallery
python main.py --gallery-id 9876543210
# Download galleries matching a pattern
python main.py --galleries "Wedding.*2023"
# Download specific folder by name pattern
python main.py --folder "Marketing.*"# Resume interrupted download
python main.py --resume
# Force overwrite existing files
python main.py --overwrite
# Custom output directory and concurrency
python main.py --output-dir /path/to/photos --concurrent-downloads 12
# Verify existing files integrity
python main.py --verify-integrity
# Verify download completion
python main.py --verify
# Export complete metadata structure
python main.py --export-metadata --metadata-format json# Refresh gallery hierarchy cache
python main.py --refresh-cache
# Show cache information
python main.py --cache-info
# Clear cache
python main.py --clear-cache# Debug single photo download
python main.py --debug-download 1234567890
# Debug first photo from gallery
python main.py --debug-gallery 9876543210
# Enable verbose logging
python main.py --log-level DEBUGWhen run without arguments, the application launches an interactive menu:
python main.pyThe interactive mode provides:
- π Folder Browser: Navigate through your Zenfolio hierarchy
- π― Selective Downloads: Choose specific folders or galleries
- β Verification Tools: Verify completed downloads
- π Queue Management: Process Zenfolio's retrieval queue
- π Status Reports: View download progress and statistics
Download original-quality photos from shared Zenfolio galleries without requiring Zenfolio login credentials. This feature uses browser automation to access photos shared via public or access-code-protected gallery links.
# Public shared galleries
https://username.zenfolio.com/p123456789/gallery-name
# Access-code protected galleries
https://username.zenfolio.com/p123456789/gallery-name?c=accesscode
- Run the application in interactive mode:
python main.py - Select "Download Shared Gallery" from the main menu
- Paste the shared gallery URL when prompted
- Photos will be downloaded to
downloads/shared_galleries/directory
The shared gallery downloader uses a two-tier approach:
- Primary: ZIP download (all photos in a single request for maximum efficiency)
- Fallback: Individual photo downloads (if ZIP download fails)
- Playwright: Browser automation library (automatically installed with dependencies)
- Chromium: Downloaded automatically on first run via
playwright install chromium
# Start interactive mode
python main.py
# Select option: "Download Shared Gallery"
# Enter URL: https://photographer.zenfolio.com/p123456789/wedding-photos
# Photos downloaded to: downloads/shared_galleries/photographer_wedding-photos/Zenfolio archives some content in a retrieval queue. The downloader can:
- π Check Queue Status: View pending items in the retrieval queue
- β‘ Process Queue: Download available items from the queue
- π Queue Analytics: Show detailed queue statistics
# Check retrieval queue status
python check_retrieval_queue.py
# Process retrieval queue (interactive mode)
python main.py # Select "Process Retrieval Queue" from menuExport complete gallery structure and metadata:
# Export to JSON format
python main.py --export-metadata --metadata-format json
# Export to CSV format
python main.py --export-metadata --metadata-format csv
# Export to both formats
python main.py --export-metadata --metadata-format bothThe application automatically saves progress and can resume interrupted downloads:
- πΎ Auto-Save: Progress saved after each gallery
- π Smart Resume: Skips completed galleries on restart
- π Progress Tracking: Shows accurate completion status
# Clear checkpoint and start fresh
python main.py --clear-checkpoint
# Resume with explicit flag (default behavior)
python main.py --resume# Verify credentials in .env file
cat .env | grep ZENFOLIO
# Test authentication
python main.py --list-galleriesSolutions:
- Verify username and password in
.env - Check account access to galleries
- Ensure no special characters in credentials
# Increase timeouts for large files
DOWNLOAD_TIMEOUT=120
REQUEST_TIMEOUT=180Solutions:
- Increase
DOWNLOAD_TIMEOUTfor large files - Reduce
CONCURRENT_DOWNLOADSif experiencing network issues - Check network stability
Solutions:
- Ensure output directory is writable:
chmod 755 ./downloads - Check disk space availability
- Verify file permissions for existing files
# Clear and rebuild cache
python main.py --clear-cache
python main.py --refresh-cache# Set debug level in .env
LOG_LEVEL=DEBUG
# Or use command line
python main.py --log-level DEBUG# Debug single photo
python main.py --debug-download 1234567890
# Debug gallery
python main.py --debug-gallery 9876543210# Monitor logs in real-time
tail -f zenfolio_downloader.log
# Search for errors
grep -i error zenfolio_downloader.log# For fast connections
CONCURRENT_DOWNLOADS=12
# For slower connections or to be gentle on servers
CONCURRENT_DOWNLOADS=4# Longer cache for stable galleries
CACHE_TTL_HOURS=168 # 1 week
# Shorter cache for frequently updated content
CACHE_TTL_HOURS=24 # 1 day- Python: 3.8+ (tested with 3.12.3)
- Dependencies: See
requirements.txt
- aiohttp: Async HTTP client for API communication
- pydantic: Data validation and settings management
- tqdm: Progress bars and status display
- click: Command-line interface framework
- loguru: Advanced logging capabilities
- tenacity: Retry logic with exponential backoff
- playwright: Browser automation for shared gallery downloads
# Install development dependencies (uncomment in requirements.txt)
pip install pytest pytest-asyncio black flake8 mypy
# Run code formatting
black .
# Run linting
flake8 .
# Run type checking
mypy .The application follows a modular architecture with clear separation of concerns:
- π API Layer: Handles Zenfolio API communication and authentication
- π₯ Download Layer: Manages concurrent downloads and retry logic
- πΎ Storage Layer: Handles file system operations and integrity checking
- π Progress Layer: Tracks progress, checkpoints, and statistics
- ποΈ Interface Layer: Provides CLI and interactive menu interfaces
- βοΈ Configuration Layer: Manages settings and environment variables
- Architecture Plan: Technical architecture overview
- Debug Guide: Comprehensive debugging information
- Gallery Listing: Gallery structure documentation
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes with proper testing
- Follow code style: Use
blackfor formatting - Add tests if applicable
- Update documentation as needed
- Submit a pull request
- Follow PEP 8 conventions
- Use type hints for all functions
- Add docstrings for public methods
- Keep functions focused and modular
- Use meaningful variable names
[Add your license information here]
For support, please:
- Check the troubleshooting section above
- Review log files for detailed error information
- Search existing issues in the repository
- Create a new issue with detailed information including:
- Error messages and log excerpts
- Configuration details (without credentials)
- Steps to reproduce the issue
- System information (OS, Python version)
- Zenfolio: For providing the API that makes this tool possible
- Contributors: Thanks to all who have contributed to this project
- Community: For feedback, bug reports, and feature suggestions