Skip to main content

🌊 Nami

An open-source CLI media downloader for Instagram, TikTok, Facebook, and X

CI PyPI Version Python Version License: MIT GitHub Stars

Nami coordinates gallery-dl and yt-dlp through a pure functional planning core and deterministic execution shell. It provides deduplicated archive indexing, multi-attempt failure classification, process isolation, and both interactive Rich terminal UI and scriptable JSON CLI modes.

Platform MatrixArchitectureInstallationQuickstartCLI ReferenceConfigurationDiagnostics


Table of Contents


Platform Support Matrix

Platform Photos & Posts Videos & Reels Stories Highlights Auth Method Primary Engine
Instagram Supported Supported Supported Supported Netscape Cookie / Anonymous gallery-dl / yt-dlp (Video Fallback)
TikTok Limited Supported Unsupported Unsupported Browser DB / Netscape Cookie yt-dlp / gallery-dl
Facebook Limited Supported Unsupported Unsupported Netscape Cookie / Anonymous gallery-dl / yt-dlp
X (Twitter) Limited Supported Unsupported Unsupported Netscape Cookie / Anonymous gallery-dl / yt-dlp

Architecture & Pipeline

Nami enforces a strict boundary between pure deterministic domain planning and stateful subprocess execution (ADR-0001):

flowchart TD
    A[Target URLs / Profiles] --> B[targets.py: Canonicalization & Endpoint Expansion]
    B --> C[planner.py: Pure Functional PlanStep Generator]
    C --> D{NamiService Orchestrator}
    D -->|Acquire File Lock| E[archive.lock]
    D -->|Select Backend| F[gallery-dl Engine]
    F -->|Success| G[Update archive.txt & Emit BatchResult]
    F -->|FailureKind.EXTRACTOR| H[Fallback: yt-dlp Engine]
    F -->|Transient Network/Timeout| I[Exponential Jittered Retry]
    H -->|Success| G
    H -->|Exhausted| J[Structured Failure Report]

Core Design Guarantees

  1. Pure Planning Layer: targets.py and planner.py compute output paths and executable PlanStep sequences without performing disk I/O or network requests.
  2. Subprocess Isolation: Zero shell interpretation (shell=False). Subprocesses execute via discrete argv tuples with full process-tree cleanup upon timeout or cancellation.
  3. Atomic File Locking: Download archives (archive.txt) are protected by non-blocking PID-keyed locks (archive.lock) to prevent concurrent process corruption.
  4. Path Containment: All output directories are verified against base_dir using safe_target_dir() to prevent path traversal or drive-escaping.

Installation

Requires Python 3.10 or newer.

python -m pip install nami

To update an existing installation:

python -m pip install --upgrade nami

Quickstart

1. Interactive Terminal UI

Run nami (or python -m nami if Python Scripts directory is not on PATH) without arguments:

nami
# or
python -m nami
╭─ Nami ───────────────────────────────────────────────────────────── v5.0.4 ─╮
│ What do you want to download?                                               │
│                                                                             │
│  1  Photos only                                                             │
│  2  Videos only                                                             │
│  3  Stories only                                                            │
│  4  Highlights only                                                         │
│  5  Photos + Videos                                                         │
│  6  Stories + Highlights                                                    │
│  7  All                                                                     │
│  8  Settings                                                                │
│  0  Exit                                                                    │
│                                                                             │
│  Save: ~/Nami/downloads                                                     │
╰─────────────────────────────────────────────────────────────────────────────╯

2. CLI Batch Invocations

# Download direct posts and reels
nami download https://www.instagram.com/p/C_EXAMPLE/ https://x.com/OpenAI/status/1234567890

# Target specific profile media
nami download https://www.instagram.com/natgeo/ --media photos,videos

# Headless batch processing with JSON stdout
nami download --profiles --platform instagram --media all --json

Workspace Hierarchy

Nami/
├── downloads/                     # Output files grouped by platform & account
│   ├── instagram/
│   │   └── natgeo/
│   │       ├── Photos/            # Downloaded image assets
│   │       │   └── archive.txt    # Deduplication tracking record
│   │       ├── Videos/            # Downloaded video assets
│   │       │   └── archive.txt
│   │       └── Stories/           # Downloaded story assets
│   │           └── archive.txt
│   └── tiktok/
│       └── example_user/
│           └── Videos/
│               └── archive.txt
├── cookies/                       # Netscape-format cookie files (*_cookies.txt)
│   ├── instagram_cookies.txt
│   ├── tiktok_cookies.txt
│   ├── facebook_cookies.txt
│   └── x_cookies.txt
└── profiles/                      # Batch target profile lists (*_profiles.txt)
    ├── instagram_profiles.txt
    ├── tiktok_profiles.txt
    ├── facebook_profiles.txt
    └── x_profiles.txt

CLI Reference

nami download

Plan and execute downloads for individual URLs or profile lists.

nami download [URL ...] [OPTIONS]
Parameter / Flag Type Description
URL ... Positional One or more content or profile URLs
--profiles Flag Batch download all targets listed in profiles_dir
--platform Option Filter or specify platform (instagram, tiktok, facebook, x)
--media Option Target media types: photos, videos, stories, highlights, all
--json Flag Output structured JSON for automation

nami setup

Initialize directory layout and generate default configuration.

nami setup [OPTIONS]
Flag Type Description
--root <PATH> Option Set root parent directory for the workspace
--cookie-templates Flag Generate template cookie files in cookies/
--json Flag Output workspace initialization result as JSON

nami doctor

Run read-only system diagnostic checks without network activity.

nami doctor [OPTIONS]
Flag Type Description
--json Flag Emit structured health checks and remediation advice in JSON
PASS  config: Configuration file is valid
PASS  python: Python 3.14.7 (>= 3.10 required)
PASS  dependencies: All required packages are installed
PASS  workspace: Base directory is writable
PASS  browser: Brave is installed and unlocked
PASS  cookies: Netscape cookies valid
PASS  urllib3: Clean namespace (no conflicts)
PASS  archive_locks: No stale locks detected

nami config

Manage persistent settings in ~/.nami/nami_config.json.

nami config show [--json]
nami config get <KEY> [--json]
nami config set <KEY> <VALUE> [--json]
nami config unset <KEY> [--json]
Key Valid Values Description
base_dir Valid path string Root directory for downloaded media
cookies_dir Valid path string Directory containing Netscape cookie files
profiles_dir Valid path string Directory containing *_profiles.txt lists
browser brave, chrome, edge, firefox Browser for automated cookie extraction
user_agent Custom string HTTP User-Agent string sent to engines
timeout_seconds Integer (> 0) Subprocess execution deadline

nami archive reset

Manage download tracking records (archive.txt) safely without data loss.

nami archive reset [OPTIONS]
Flag Type Description
--all Flag Target all archives across all platforms
--platform <NAME> Option Target archives for a specific platform
--target <KEY> Option Target archives for a specific account/target
--media <KIND> Option Filter archives by media kind
--dry-run Flag Preview affected archives without modifying disk
--delete Flag Permanently delete matching archives (default: create .bak)
--yes Flag Confirm mutation without interactive prompt
--json Flag Output affected archive list in JSON

Authentication & Cookies

Place exported cookies into cookies_dir. Nami verifies that files contain genuine 7-column rows before mounting them to child engines:

  • instagram_cookies.txt or instagram.com_cookies.txt
  • tiktok_cookies.txt or tiktok.com_cookies.txt
  • facebook_cookies.txt or facebook.com_cookies.txt
  • x_cookies.txt or x.com_cookies.txt

2. Browser Database Session Extraction

For TikTok downloads without an explicit cookie file, Nami extracts session tokens directly from local browser stores (brave, chrome, edge, firefox).


Failure Taxonomy & Retry Policy

failures.py maps engine stderr diagnostics into typed FailureKind categories:

Failure Category Classification Criteria Recovery Strategy
FailureKind.AUTH HTTP 401, login required, session expired 1 anonymous retry if credentials were provided
FailureKind.COOKIE Corrupt or undecryptable cookie file 1 anonymous retry if credentials were provided
FailureKind.RATE_LIMIT HTTP 429, temporary platform block Terminate immediately without cross-engine churn
FailureKind.NETWORK Connection reset, TLS failure, DNS timeout Up to 3 attempts with exponential jittered backoff
FailureKind.EXTRACTOR Route failure, extractor deprecation 1 retry on secondary engine (yt-dlp)
FailureKind.NOT_FOUND HTTP 404, user not found, private media Stop immediately with Outcome.NO_RESULTS
FailureKind.DEPENDENCY Missing binary or unimportable module Stop immediately
FailureKind.TIMEOUT Subprocess wall-clock deadline exceeded Up to 3 attempts with exponential backoff
FailureKind.LOCKED Archive lock contention or account challenge Stop immediately

Deterministic Exit Codes

Exit Code Identifier Meaning
0 SUCCESS All plan steps downloaded or already up to date
1 FAILED Unrecoverable error occurred on one or more operations
2 INVALID Malformed CLI syntax, invalid URL, or corrupted configuration
3 PARTIAL / WARN Mixed outcomes, unsupported operations, or doctor warnings
4 NO_RESULTS Extractor ran successfully but found zero downloadable items
130 CANCELLED Execution interrupted via SIGINT (Ctrl+C)

Configuration & Environment Variables

Setting Key Environment Variable Default Value Description
base_dir NAMI_BASE_DIR ~/Nami/downloads Root directory for downloads
cookies_dir NAMI_COOKIES_DIR ~/Nami/cookies Directory for Netscape cookies
profiles_dir NAMI_PROFILES_DIR ~/Nami/profiles Directory for target profile lists
browser NAMI_BROWSER brave Browser for automated cookie discovery
user_agent NAMI_USER_AGENT Chrome Default HTTP User-Agent header
timeout_seconds NAMI_TIMEOUT_SECONDS 1800 Process execution deadline in seconds
NAMI_THEME auto Terminal styling theme (dark, light, auto)
NAMI_SKIP_ENV_CHECK 0 Set to 1 to bypass startup environment checks

Development & Verification

Local Environment Setup

git clone https://github.com/OpenSelena/nami.git
cd nami
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"

Verification Commands

# Run pytest unit test suite
python -m pytest

# Run Ruff linter and code formatter checks
python -m ruff check src tests
python -m ruff format --check src tests

# Verify package build & metadata
python -m build
python -m twine check dist/*

License

Distributed under the MIT License. Developed and maintained by Igect under OpenSelena.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nami-5.0.4.tar.gz (69.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nami-5.0.4-py3-none-any.whl (55.1 kB view details)

Uploaded Python 3

File details

Details for the file nami-5.0.4.tar.gz.

File metadata

  • Download URL: nami-5.0.4.tar.gz
  • Upload date:
  • Size: 69.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for nami-5.0.4.tar.gz
Algorithm Hash digest
SHA256 1b8dbad02d8294a8fefb4d04021a30953f5008f67187014b9d6286a46c9f6321
MD5 33efd6153a90e1d0045f68cc0fadd86b
BLAKE2b-256 62fc61c25302451906b19507a28da61b883c98b8157b1c74d8eed001f399af38

See more details on using hashes here.

Provenance

The following attestation bundles were made for nami-5.0.4.tar.gz:

Publisher: publish.yml on OpenSelena/nami

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file nami-5.0.4-py3-none-any.whl.

File metadata

  • Download URL: nami-5.0.4-py3-none-any.whl
  • Upload date:
  • Size: 55.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for nami-5.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 4bd1ca16b3e84971842c0d3d792084c1c7af5022c2ea1c9804c2162b178a7c3f
MD5 beb8522d65eed84dcec84d6356d15571
BLAKE2b-256 f46942be1357785a44b6fa7816a01a0e25d5ff99a4559e558fddde9987989bcf

See more details on using hashes here.

Provenance

The following attestation bundles were made for nami-5.0.4-py3-none-any.whl:

Publisher: publish.yml on OpenSelena/nami

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

5.0.6

2 files

This release

5.0.4 This release

2 files

5.0.3

2 files

5.0.2

2 files

5.0.1

2 files

5.0.0

2 files

4.0.0

2 files

3.0.4

2 files

3.0.3

2 files

3.0.2

2 files

3.0.1

2 files

3.0.0

2 files

2.5.2

2 files

2.5.1

2 files

2.5.0

2 files

2.4.1

2 files

2.4.0

2 files

2.3.9

2 files

2.3.8

2 files

2.3.7

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page