instagram-dl 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- instagram_dl-0.0.1/.github/workflows/docs.yml +46 -0
- instagram_dl-0.0.1/.github/workflows/lint.yml +33 -0
- instagram_dl-0.0.1/.github/workflows/tests.yml +22 -0
- instagram_dl-0.0.1/.gitignore +16 -0
- instagram_dl-0.0.1/CHANGELOG.md +31 -0
- instagram_dl-0.0.1/CONTRIBUTING.md +94 -0
- instagram_dl-0.0.1/LICENSE +21 -0
- instagram_dl-0.0.1/PKG-INFO +207 -0
- instagram_dl-0.0.1/README.md +141 -0
- instagram_dl-0.0.1/docs/architecture.md +94 -0
- instagram_dl-0.0.1/docs/backends.md +84 -0
- instagram_dl-0.0.1/docs/basic-usage.md +130 -0
- instagram_dl-0.0.1/docs/changelog.md +1 -0
- instagram_dl-0.0.1/docs/cli-reference.md +152 -0
- instagram_dl-0.0.1/docs/contributing.md +1 -0
- instagram_dl-0.0.1/docs/index.md +46 -0
- instagram_dl-0.0.1/docs/installation.md +73 -0
- instagram_dl-0.0.1/docs/python-api.md +161 -0
- instagram_dl-0.0.1/docs/troubleshooting.md +134 -0
- instagram_dl-0.0.1/insta_dl/__init__.py +1 -0
- instagram_dl-0.0.1/insta_dl/__main__.py +6 -0
- instagram_dl-0.0.1/insta_dl/backend.py +49 -0
- instagram_dl-0.0.1/insta_dl/backends/__init__.py +14 -0
- instagram_dl-0.0.1/insta_dl/backends/_hiker_map.py +159 -0
- instagram_dl-0.0.1/insta_dl/backends/aiograpi_backend.py +66 -0
- instagram_dl-0.0.1/insta_dl/backends/hiker.py +236 -0
- instagram_dl-0.0.1/insta_dl/cli.py +120 -0
- instagram_dl-0.0.1/insta_dl/downloader.py +195 -0
- instagram_dl-0.0.1/insta_dl/exceptions.py +22 -0
- instagram_dl-0.0.1/insta_dl/filestore.py +71 -0
- instagram_dl-0.0.1/insta_dl/latest_stamps.py +44 -0
- instagram_dl-0.0.1/insta_dl/models.py +80 -0
- instagram_dl-0.0.1/mkdocs.yml +67 -0
- instagram_dl-0.0.1/pyproject.toml +125 -0
- instagram_dl-0.0.1/tests/__init__.py +0 -0
- instagram_dl-0.0.1/tests/test_cli.py +128 -0
- instagram_dl-0.0.1/tests/test_cli_run.py +140 -0
- instagram_dl-0.0.1/tests/test_downloader.py +57 -0
- instagram_dl-0.0.1/tests/test_downloader_integration.py +237 -0
- instagram_dl-0.0.1/tests/test_edges.py +114 -0
- instagram_dl-0.0.1/tests/test_filestore.py +106 -0
- instagram_dl-0.0.1/tests/test_hardening.py +294 -0
- instagram_dl-0.0.1/tests/test_hiker_backend.py +76 -0
- instagram_dl-0.0.1/tests/test_hiker_backend_http.py +294 -0
- instagram_dl-0.0.1/tests/test_hiker_map.py +183 -0
- instagram_dl-0.0.1/tests/test_latest_stamps.py +58 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- "docs/**"
|
|
8
|
+
- "mkdocs.yml"
|
|
9
|
+
- "README.md"
|
|
10
|
+
- "CONTRIBUTING.md"
|
|
11
|
+
- "CHANGELOG.md"
|
|
12
|
+
- ".github/workflows/docs.yml"
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
pages: write
|
|
18
|
+
id-token: write
|
|
19
|
+
|
|
20
|
+
concurrency:
|
|
21
|
+
group: docs-deploy
|
|
22
|
+
cancel-in-progress: false
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
build:
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
- uses: actions/setup-python@v5
|
|
30
|
+
with:
|
|
31
|
+
python-version: "3.12"
|
|
32
|
+
cache: pip
|
|
33
|
+
- run: pip install -e '.[docs]'
|
|
34
|
+
- run: mkdocs build --strict --site-dir _site
|
|
35
|
+
- uses: actions/upload-pages-artifact@v3
|
|
36
|
+
with:
|
|
37
|
+
path: _site
|
|
38
|
+
|
|
39
|
+
deploy:
|
|
40
|
+
needs: build
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
environment:
|
|
43
|
+
name: github-pages
|
|
44
|
+
steps:
|
|
45
|
+
- id: deployment
|
|
46
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: lint
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
ruff:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.12"
|
|
20
|
+
cache: pip
|
|
21
|
+
- run: pip install -e '.[lint]'
|
|
22
|
+
- run: ruff check insta_dl tests
|
|
23
|
+
|
|
24
|
+
mypy:
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
- uses: actions/setup-python@v5
|
|
29
|
+
with:
|
|
30
|
+
python-version: "3.12"
|
|
31
|
+
cache: pip
|
|
32
|
+
- run: pip install -e '.[lint]'
|
|
33
|
+
- run: mypy insta_dl
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.12"
|
|
20
|
+
cache: pip
|
|
21
|
+
- run: pip install -e '.[dev]'
|
|
22
|
+
- run: pytest --cov=insta_dl --cov-report=term-missing --cov-fail-under=90
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to insta-dl. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning follows [SemVer](https://semver.org/spec/v2.0.0.html).
|
|
4
|
+
|
|
5
|
+
## [0.0.1] — 2026-04-24
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Initial async-first skeleton with pluggable backend interface (`InstagramBackend` ABC).
|
|
10
|
+
- HikerAPI backend (`HikerBackend`) with cursor pagination, dict→DTO mapping, and streaming downloads via `httpx.AsyncClient`.
|
|
11
|
+
- `Downloader` facade orchestrating profile/post/hashtag/stories/highlights/comments downloads with consistent file layout.
|
|
12
|
+
- CLI accepting profile names, `#hashtag`, `post:SHORTCODE`, and full `instagram.com/p/...`, `/reel/`, `/tv/` URLs (case-insensitive, anchored regex against host spoofing).
|
|
13
|
+
- Sidecar JSON metadata per post; optional `--comments` sidecar streamed to disk.
|
|
14
|
+
- `--fast-update` + `--latest-stamps` for incremental archive updates (INI-backed state).
|
|
15
|
+
- `safe_component()` path sanitizer applied to every user-controlled component (username, owner, hashtag, highlight title, post code).
|
|
16
|
+
- Hardening: HTTPS-only allowlist for CDN downloads (`*.cdninstagram.com`, `*.fbcdn.net`), manual redirect loop with cap, signed-token strip from sidecar URLs, `.part` files with UUID suffixes, configurable max-download size (default 500 MB), Windows reserved-name and bidi/zero-width character handling.
|
|
17
|
+
- Test suite: 198 pytest cases at 95% coverage. `httpx.MockTransport` used for CDN, fake hikerapi client for upstream.
|
|
18
|
+
- MkDocs Material documentation site at `docs/`.
|
|
19
|
+
|
|
20
|
+
### Stubbed
|
|
21
|
+
|
|
22
|
+
- `AiograpiBackend` — interface defined, methods raise `NotImplementedError` pending an upstream sync.
|
|
23
|
+
- `--post-filter` — parsed but ignored; planned implementation uses AST-restricted compile (no raw `eval`).
|
|
24
|
+
|
|
25
|
+
### Known limitations
|
|
26
|
+
|
|
27
|
+
- No retry/backoff on 429 / 5xx / connection reset (relies on hikerapi defaults).
|
|
28
|
+
- No support for `:feed`, `:saved`, or DMs (account-bound, blocked on aiograpi).
|
|
29
|
+
- Comments sidecar is a single JSON array — fine for posts with thousands of comments, may want JSONL for hundreds of thousands.
|
|
30
|
+
|
|
31
|
+
[0.0.1]: https://github.com/subzeroid/insta-dl/releases/tag/v0.0.1
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Contributing to insta-dl
|
|
2
|
+
|
|
3
|
+
Thanks for considering a contribution. This document covers the dev workflow.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone git@github.com:subzeroid/insta-dl.git
|
|
9
|
+
cd insta-dl
|
|
10
|
+
python -m venv .venv && source .venv/bin/activate
|
|
11
|
+
pip install -e '.[dev]'
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Python 3.11+ required (we use `dataclass(slots=True)`, `X | Y` unions, `datetime.fromisoformat` with `Z`).
|
|
15
|
+
|
|
16
|
+
## Running tests
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pytest # all tests
|
|
20
|
+
pytest -k hiker # subset
|
|
21
|
+
pytest --cov=insta_dl --cov-report=term-missing # with coverage
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The suite is fully offline — no real HikerAPI or Instagram calls. Network is mocked via `httpx.MockTransport` and a fake hikerapi client.
|
|
25
|
+
|
|
26
|
+
Coverage targets: keep pure-logic modules at 100% (`models`, `filestore`, `latest_stamps`, `exceptions`). Everything else: 90%+ where reasonable. Don't write tests for `__main__.py`.
|
|
27
|
+
|
|
28
|
+
## Project layout
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
insta_dl/
|
|
32
|
+
cli.py # argparse + target dispatch
|
|
33
|
+
downloader.py # Downloader facade (orchestrates files, mtime, fast-update)
|
|
34
|
+
backend.py # InstagramBackend ABC — async iterators
|
|
35
|
+
models.py # DTOs (Profile, Post, StoryItem, Highlight, Comment)
|
|
36
|
+
filestore.py # safe_component, post_filename, mtime
|
|
37
|
+
latest_stamps.py # INI state for --fast-update
|
|
38
|
+
exceptions.py # error hierarchy
|
|
39
|
+
backends/
|
|
40
|
+
hiker.py # HikerAPI adapter (httpx + AsyncClient)
|
|
41
|
+
_hiker_map.py # raw dict → DTO mappers
|
|
42
|
+
aiograpi_backend.py # aiograpi adapter (stub; in progress)
|
|
43
|
+
tests/
|
|
44
|
+
test_*.py # pytest, asyncio mode = auto
|
|
45
|
+
docs/
|
|
46
|
+
*.md # MkDocs Material site
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Adding a backend
|
|
50
|
+
|
|
51
|
+
1. Implement `insta_dl.backend.InstagramBackend` in `insta_dl/backends/<name>.py`. All methods are `async`; iterators are `AsyncIterator[...]`.
|
|
52
|
+
2. Map raw responses to DTOs in `insta_dl/backends/_<name>_map.py`. Don't fabricate missing fields — raise `ValueError` so the caller can decide to skip.
|
|
53
|
+
3. Implement `download_resource(url, dest)` with:
|
|
54
|
+
- host allowlist (`*.cdninstagram.com`, `*.fbcdn.net`)
|
|
55
|
+
- https-only scheme check
|
|
56
|
+
- manual redirect loop with limit
|
|
57
|
+
- `.part` file with `uuid.uuid4().hex` suffix → `os.replace` on success, `unlink` on failure
|
|
58
|
+
- byte budget against `_max_bytes`
|
|
59
|
+
See `HikerBackend.download_resource` for the reference.
|
|
60
|
+
4. Register in `insta_dl/backends/__init__.py:make_backend`.
|
|
61
|
+
5. Add tests in `tests/test_<name>_backend.py` using `httpx.MockTransport` for the CDN and a fake client for the upstream API.
|
|
62
|
+
|
|
63
|
+
The `Downloader` facade and DTOs are backend-agnostic — never let backend-specific types leak past the adapter layer.
|
|
64
|
+
|
|
65
|
+
## Code style
|
|
66
|
+
|
|
67
|
+
- No emojis in code or docs (unless the user asked for them).
|
|
68
|
+
- No comments unless the *why* is non-obvious. Code should self-document via naming.
|
|
69
|
+
- Default to writing nothing speculative (no helpers for hypothetical future requirements).
|
|
70
|
+
- `from __future__ import annotations` everywhere — keeps annotations lazy and string-based.
|
|
71
|
+
- Lazy imports for heavy backend dependencies (`hikerapi`, `aiograpi`) — top-level import of a backend module must succeed without the upstream library installed.
|
|
72
|
+
|
|
73
|
+
## Documentation
|
|
74
|
+
|
|
75
|
+
The MkDocs site lives in `docs/`. To preview locally:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install -e '.[docs]'
|
|
79
|
+
mkdocs serve
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Then open <http://localhost:8000>. The site auto-deploys to GitHub Pages on push to `main` via `.github/workflows/docs.yml`.
|
|
83
|
+
|
|
84
|
+
## Pull requests
|
|
85
|
+
|
|
86
|
+
- Branch from `main`, rebase before opening the PR.
|
|
87
|
+
- One logical change per PR.
|
|
88
|
+
- All tests must pass; coverage shouldn't drop more than 1%.
|
|
89
|
+
- Update `CHANGELOG.md` under "Unreleased".
|
|
90
|
+
- For new CLI flags or backend methods, update `docs/cli-reference.md` and `docs/backends.md`.
|
|
91
|
+
|
|
92
|
+
## Security
|
|
93
|
+
|
|
94
|
+
If you find a vulnerability (path traversal, SSRF bypass, signed-token leak, etc.), please open a private security advisory on GitHub rather than a public issue.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 subzeroid
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: instagram-dl
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Async Instagram downloader CLI — profiles, posts, reels, stories, highlights, hashtags, comments. Pluggable backends (HikerAPI / aiograpi).
|
|
5
|
+
Project-URL: Homepage, https://subzeroid.github.io/insta-dl/
|
|
6
|
+
Project-URL: Documentation, https://subzeroid.github.io/insta-dl/
|
|
7
|
+
Project-URL: Repository, https://github.com/subzeroid/insta-dl
|
|
8
|
+
Project-URL: Issues, https://github.com/subzeroid/insta-dl/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/subzeroid/insta-dl/blob/main/CHANGELOG.md
|
|
10
|
+
Author: subzeroid
|
|
11
|
+
License: MIT License
|
|
12
|
+
|
|
13
|
+
Copyright (c) 2026 subzeroid
|
|
14
|
+
|
|
15
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
16
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
17
|
+
in the Software without restriction, including without limitation the rights
|
|
18
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
19
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
20
|
+
furnished to do so, subject to the following conditions:
|
|
21
|
+
|
|
22
|
+
The above copyright notice and this permission notice shall be included in all
|
|
23
|
+
copies or substantial portions of the Software.
|
|
24
|
+
|
|
25
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
26
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
27
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
28
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
29
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
30
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
31
|
+
SOFTWARE.
|
|
32
|
+
License-File: LICENSE
|
|
33
|
+
Keywords: aiograpi,async,cli,downloader,hikerapi,instagram,instagram-downloader,instagram-scraper,osint
|
|
34
|
+
Classifier: Development Status :: 3 - Alpha
|
|
35
|
+
Classifier: Environment :: Console
|
|
36
|
+
Classifier: Intended Audience :: Developers
|
|
37
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
38
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
39
|
+
Classifier: Operating System :: OS Independent
|
|
40
|
+
Classifier: Programming Language :: Python
|
|
41
|
+
Classifier: Programming Language :: Python :: 3
|
|
42
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
43
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
44
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
45
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
46
|
+
Classifier: Topic :: Internet
|
|
47
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
48
|
+
Classifier: Topic :: Multimedia :: Video
|
|
49
|
+
Classifier: Topic :: Utilities
|
|
50
|
+
Classifier: Typing :: Typed
|
|
51
|
+
Requires-Python: >=3.11
|
|
52
|
+
Requires-Dist: aiograpi
|
|
53
|
+
Requires-Dist: hikerapi
|
|
54
|
+
Provides-Extra: dev
|
|
55
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
56
|
+
Requires-Dist: pytest-cov>=5; extra == 'dev'
|
|
57
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
58
|
+
Provides-Extra: docs
|
|
59
|
+
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
|
|
60
|
+
Requires-Dist: mkdocs>=1.6; extra == 'docs'
|
|
61
|
+
Requires-Dist: pymdown-extensions>=10; extra == 'docs'
|
|
62
|
+
Provides-Extra: lint
|
|
63
|
+
Requires-Dist: mypy>=1.11; extra == 'lint'
|
|
64
|
+
Requires-Dist: ruff>=0.6; extra == 'lint'
|
|
65
|
+
Description-Content-Type: text/markdown
|
|
66
|
+
|
|
67
|
+
# insta-dl
|
|
68
|
+
|
|
69
|
+
[](https://www.python.org/downloads/)
|
|
70
|
+
[](LICENSE)
|
|
71
|
+
[]()
|
|
72
|
+
[]()
|
|
73
|
+
[]()
|
|
74
|
+
|
|
75
|
+
Async command-line downloader for Instagram. Profiles, posts, reels, stories, highlights, hashtags, and comments — saved to disk with the original timestamps preserved.
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install instagram-dl # installs the `insta-dl` command
|
|
79
|
+
|
|
80
|
+
export HIKERAPI_TOKEN=your_token
|
|
81
|
+
insta-dl instagram
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**insta-dl**
|
|
85
|
+
|
|
86
|
+
- downloads **profiles, hashtags, single posts, reels, stories, highlights, and comments**,
|
|
87
|
+
- preserves the **original `taken_at` timestamp** as file mtime so Photos/Finder sort correctly,
|
|
88
|
+
- writes a **JSON metadata sidecar** next to every post (caption, like count, location, owner),
|
|
89
|
+
- supports **incremental updates** with `--fast-update` and `--latest-stamps`,
|
|
90
|
+
- accepts profile names, `#hashtag`, post shortcodes, and full `instagram.com` URLs,
|
|
91
|
+
- ships **two interchangeable backends**: a paid commercial API (HikerAPI, no Instagram session, no ban risk) and an open-source private-API library (aiograpi, your own login).
|
|
92
|
+
|
|
93
|
+
```text
|
|
94
|
+
insta-dl [--backend hiker|aiograpi]
|
|
95
|
+
[--dest DIR] [--fast-update] [--latest-stamps FILE]
|
|
96
|
+
[--stories] [--highlights] [--comments]
|
|
97
|
+
profile | "#hashtag" | post:SHORTCODE | https://instagram.com/...
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
📖 **[Full documentation](https://subzeroid.github.io/insta-dl/)** — installation, CLI reference, backends comparison, Python API, troubleshooting.
|
|
101
|
+
|
|
102
|
+
## How to download an Instagram profile
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
export HIKERAPI_TOKEN=$(cat ~/.config/hikerapi-token)
|
|
106
|
+
insta-dl --dest ./out instagram
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
This grabs every post, names files `2026-04-21_16-04-15_DXZlTiKEpxw.mp4`, and writes a metadata sidecar next to each.
|
|
110
|
+
|
|
111
|
+
## How to keep a local archive in sync
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
insta-dl --fast-update --latest-stamps ./stamps.ini --dest ./out instagram
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`--fast-update` stops at the first post that's already on disk; `--latest-stamps` records the newest `taken_at` per profile so even a deleted local copy can be resumed.
|
|
118
|
+
|
|
119
|
+
## How to download a single post or reel
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
insta-dl post:DXZlTiKEpxw
|
|
123
|
+
insta-dl https://www.instagram.com/p/DXZlTiKEpxw/
|
|
124
|
+
insta-dl https://www.instagram.com/reel/DXZlTiKEpxw/
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## How to download a hashtag
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
insta-dl '#sunset' --dest ./out
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Pulls the recent feed for the tag into `./out/#sunset/`.
|
|
134
|
+
|
|
135
|
+
## How to grab stories and highlights
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
insta-dl --stories --highlights --dest ./out instagram
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Stories and highlights land under `<dest>/<username>/stories/` and `<dest>/<username>/highlights/<id>_<title>/`.
|
|
142
|
+
|
|
143
|
+
## How to save comments alongside posts
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
insta-dl --comments --dest ./out instagram
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Each post gets a `..._comments.json` sidecar streamed to disk.
|
|
150
|
+
|
|
151
|
+
## Backends
|
|
152
|
+
|
|
153
|
+
Pick the one that matches how you want to authenticate.
|
|
154
|
+
|
|
155
|
+
| | **hiker** (default) | **aiograpi** *(in development)* |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| Auth | API token | Instagram login + 2FA |
|
|
158
|
+
| Cost | Paid per request, [**100 free requests**](https://hikerapi.com/p/18j4ib4j) to start | Free |
|
|
159
|
+
| Account ban risk | None — no Instagram session involved | Real, mitigated by session reuse |
|
|
160
|
+
| Stability vs. Instagram changes | High (managed proxy) | Brittle |
|
|
161
|
+
| Private profiles | What HikerAPI exposes | Anything your account can see |
|
|
162
|
+
|
|
163
|
+
Switch with `--backend`:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
insta-dl --backend hiker --hiker-token TOKEN instagram
|
|
167
|
+
insta-dl --backend aiograpi --login USER --password PASS --session ./session.json instagram
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Detailed comparison and auth setup: see the [backends documentation](https://subzeroid.github.io/insta-dl/backends/).
|
|
171
|
+
|
|
172
|
+
## Output layout
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
<dest>/<username>/
|
|
176
|
+
2026-04-21_16-04-15_DXZlTiKEpxw.mp4
|
|
177
|
+
2026-04-21_16-04-15_DXZlTiKEpxw.json # metadata sidecar
|
|
178
|
+
2026-04-21_16-04-15_DXZlTiKEpxw_comments.json # with --comments
|
|
179
|
+
stories/
|
|
180
|
+
2026-04-21_18-30-00_178290.jpg # with --stories
|
|
181
|
+
highlights/
|
|
182
|
+
17991_Travel/ # with --highlights
|
|
183
|
+
2025-10-12_19-20-30_4011.jpg
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Hashtag downloads land under `<dest>/#<tag>/`; single-post downloads use the post owner's username (or `owner_pk` fallback).
|
|
187
|
+
|
|
188
|
+
## Status
|
|
189
|
+
|
|
190
|
+
This is **alpha**. The hiker backend is functional end-to-end (197 tests, 95% coverage). The aiograpi backend is stubbed pending an upstream sync. CLI flags and output layout are stable; Python API may still shift.
|
|
191
|
+
|
|
192
|
+
What's not yet implemented:
|
|
193
|
+
|
|
194
|
+
- private profiles requiring login (waiting on aiograpi)
|
|
195
|
+
- `:feed` and `:saved` (account-bound, blocked on aiograpi)
|
|
196
|
+
- post-filter expressions (planned: AST-restricted eval)
|
|
197
|
+
- automatic retry/backoff on 429/5xx
|
|
198
|
+
|
|
199
|
+
See the [changelog](CHANGELOG.md) for what landed when, and [contributing](CONTRIBUTING.md) for how to help.
|
|
200
|
+
|
|
201
|
+
## Contributing
|
|
202
|
+
|
|
203
|
+
Bug reports, fixes, and backend implementations welcome. Start with [CONTRIBUTING.md](CONTRIBUTING.md). Tests: `pip install -e .[dev] && pytest`.
|
|
204
|
+
|
|
205
|
+
## Disclaimer
|
|
206
|
+
|
|
207
|
+
insta-dl is not affiliated with, authorized, maintained, or endorsed by Instagram or Meta. Use at your own risk and respect the rights of content creators. Licensed under [MIT](LICENSE).
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# insta-dl
|
|
2
|
+
|
|
3
|
+
[](https://www.python.org/downloads/)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[]()
|
|
6
|
+
[]()
|
|
7
|
+
[]()
|
|
8
|
+
|
|
9
|
+
Async command-line downloader for Instagram. Profiles, posts, reels, stories, highlights, hashtags, and comments — saved to disk with the original timestamps preserved.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install instagram-dl # installs the `insta-dl` command
|
|
13
|
+
|
|
14
|
+
export HIKERAPI_TOKEN=your_token
|
|
15
|
+
insta-dl instagram
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
**insta-dl**
|
|
19
|
+
|
|
20
|
+
- downloads **profiles, hashtags, single posts, reels, stories, highlights, and comments**,
|
|
21
|
+
- preserves the **original `taken_at` timestamp** as file mtime so Photos/Finder sort correctly,
|
|
22
|
+
- writes a **JSON metadata sidecar** next to every post (caption, like count, location, owner),
|
|
23
|
+
- supports **incremental updates** with `--fast-update` and `--latest-stamps`,
|
|
24
|
+
- accepts profile names, `#hashtag`, post shortcodes, and full `instagram.com` URLs,
|
|
25
|
+
- ships **two interchangeable backends**: a paid commercial API (HikerAPI, no Instagram session, no ban risk) and an open-source private-API library (aiograpi, your own login).
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
insta-dl [--backend hiker|aiograpi]
|
|
29
|
+
[--dest DIR] [--fast-update] [--latest-stamps FILE]
|
|
30
|
+
[--stories] [--highlights] [--comments]
|
|
31
|
+
profile | "#hashtag" | post:SHORTCODE | https://instagram.com/...
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
📖 **[Full documentation](https://subzeroid.github.io/insta-dl/)** — installation, CLI reference, backends comparison, Python API, troubleshooting.
|
|
35
|
+
|
|
36
|
+
## How to download an Instagram profile
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
export HIKERAPI_TOKEN=$(cat ~/.config/hikerapi-token)
|
|
40
|
+
insta-dl --dest ./out instagram
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
This grabs every post, names files `2026-04-21_16-04-15_DXZlTiKEpxw.mp4`, and writes a metadata sidecar next to each.
|
|
44
|
+
|
|
45
|
+
## How to keep a local archive in sync
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
insta-dl --fast-update --latest-stamps ./stamps.ini --dest ./out instagram
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`--fast-update` stops at the first post that's already on disk; `--latest-stamps` records the newest `taken_at` per profile so even a deleted local copy can be resumed.
|
|
52
|
+
|
|
53
|
+
## How to download a single post or reel
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
insta-dl post:DXZlTiKEpxw
|
|
57
|
+
insta-dl https://www.instagram.com/p/DXZlTiKEpxw/
|
|
58
|
+
insta-dl https://www.instagram.com/reel/DXZlTiKEpxw/
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## How to download a hashtag
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
insta-dl '#sunset' --dest ./out
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Pulls the recent feed for the tag into `./out/#sunset/`.
|
|
68
|
+
|
|
69
|
+
## How to grab stories and highlights
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
insta-dl --stories --highlights --dest ./out instagram
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Stories and highlights land under `<dest>/<username>/stories/` and `<dest>/<username>/highlights/<id>_<title>/`.
|
|
76
|
+
|
|
77
|
+
## How to save comments alongside posts
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
insta-dl --comments --dest ./out instagram
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Each post gets a `..._comments.json` sidecar streamed to disk.
|
|
84
|
+
|
|
85
|
+
## Backends
|
|
86
|
+
|
|
87
|
+
Pick the one that matches how you want to authenticate.
|
|
88
|
+
|
|
89
|
+
| | **hiker** (default) | **aiograpi** *(in development)* |
|
|
90
|
+
|---|---|---|
|
|
91
|
+
| Auth | API token | Instagram login + 2FA |
|
|
92
|
+
| Cost | Paid per request, [**100 free requests**](https://hikerapi.com/p/18j4ib4j) to start | Free |
|
|
93
|
+
| Account ban risk | None — no Instagram session involved | Real, mitigated by session reuse |
|
|
94
|
+
| Stability vs. Instagram changes | High (managed proxy) | Brittle |
|
|
95
|
+
| Private profiles | What HikerAPI exposes | Anything your account can see |
|
|
96
|
+
|
|
97
|
+
Switch with `--backend`:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
insta-dl --backend hiker --hiker-token TOKEN instagram
|
|
101
|
+
insta-dl --backend aiograpi --login USER --password PASS --session ./session.json instagram
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Detailed comparison and auth setup: see the [backends documentation](https://subzeroid.github.io/insta-dl/backends/).
|
|
105
|
+
|
|
106
|
+
## Output layout
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
<dest>/<username>/
|
|
110
|
+
2026-04-21_16-04-15_DXZlTiKEpxw.mp4
|
|
111
|
+
2026-04-21_16-04-15_DXZlTiKEpxw.json # metadata sidecar
|
|
112
|
+
2026-04-21_16-04-15_DXZlTiKEpxw_comments.json # with --comments
|
|
113
|
+
stories/
|
|
114
|
+
2026-04-21_18-30-00_178290.jpg # with --stories
|
|
115
|
+
highlights/
|
|
116
|
+
17991_Travel/ # with --highlights
|
|
117
|
+
2025-10-12_19-20-30_4011.jpg
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Hashtag downloads land under `<dest>/#<tag>/`; single-post downloads use the post owner's username (or `owner_pk` fallback).
|
|
121
|
+
|
|
122
|
+
## Status
|
|
123
|
+
|
|
124
|
+
This is **alpha**. The hiker backend is functional end-to-end (197 tests, 95% coverage). The aiograpi backend is stubbed pending an upstream sync. CLI flags and output layout are stable; Python API may still shift.
|
|
125
|
+
|
|
126
|
+
What's not yet implemented:
|
|
127
|
+
|
|
128
|
+
- private profiles requiring login (waiting on aiograpi)
|
|
129
|
+
- `:feed` and `:saved` (account-bound, blocked on aiograpi)
|
|
130
|
+
- post-filter expressions (planned: AST-restricted eval)
|
|
131
|
+
- automatic retry/backoff on 429/5xx
|
|
132
|
+
|
|
133
|
+
See the [changelog](CHANGELOG.md) for what landed when, and [contributing](CONTRIBUTING.md) for how to help.
|
|
134
|
+
|
|
135
|
+
## Contributing
|
|
136
|
+
|
|
137
|
+
Bug reports, fixes, and backend implementations welcome. Start with [CONTRIBUTING.md](CONTRIBUTING.md). Tests: `pip install -e .[dev] && pytest`.
|
|
138
|
+
|
|
139
|
+
## Disclaimer
|
|
140
|
+
|
|
141
|
+
insta-dl is not affiliated with, authorized, maintained, or endorsed by Instagram or Meta. Use at your own risk and respect the rights of content creators. Licensed under [MIT](LICENSE).
|