Metadata-Version: 2.4
Name: basketcase
Version: 8.0.2
Summary: Download media from Instagram
Author-email: Douglas Silva <doug.hs@proton.me>
License-Expression: GPL-3.0-or-later
Project-URL: Homepage, https://gitlab.com/crimson.king/basketcase
Project-URL: Bug Tracker, https://gitlab.com/crimson.king/basketcase/-/issues
Keywords: instagram,story,stories
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx[brotli,zstd]~=0.28
Requires-Dist: beautifulsoup4~=4.0
Requires-Dist: lxml~=6.0
Requires-Dist: pillow~=12.0
Dynamic: license-file

# BasketCase
Download images and videos from Instagram.

Notable features:
- Stories can be downloaded **without being seen**.
- Downloads media from a list of URLs.
- Downloads media of the highest quality available.
- Downloads a high-quality profile picture.

["Green Day - Basket Case" on YouTube](https://www.youtube.com/watch?v=NUTGr5t3MoY) 🤕

## Installation methods
### pipx
[pipx](https://pipx.pypa.io/stable/) greatly simplifies user installations
and avoids conflicts with the system by isolating every program in its
own virtual environment.
```sh
pipx install basketcase
```

### venv
Or you could simply install it in a virtual environment created with
the `venv` module.
```sh
python -m venv ~/.venv
. ~/.venv/bin/activate
pip install basketcase
```

## Command-line usage
```sh
basketcase get "https://instagram.com/p/POST_ID"
```

> Downloaded resources will be stored in the current working directory
> by default. Override with the `get --output` option.

To download from multiple URLs, create a text file (e.g. `urls.txt`)
and populate it with resource URLs:

```
https://instagram.com/p/POST_ID
https://instagram.com/reel/REEL_ID
https://instagram.com/USERNAME
```

```sh
basketcase get ./urls.txt
```

See `--help` for more info.

### Supported URLs
| Supported URL                                              | Description                                                                      |
|------------------------------------------------------------|----------------------------------------------------------------------------------|
| `https://instagram.com/USERNAME`                           | User profile. Downloads stories from the past 24 hours, and the profile picture. |
| `https://instagram.com/p/POST_ID`                          | Standard feed post                                                               |
| `https://instagram.com/reel/REEL_ID`                       | Reels movie                                                                      |
| `https://instagram.com/stories/highlights/HIGHLIGHT_ID/`   | A collection of stories, or "highlights"                                         |
| `https://instagram.com/s/CODE`                             | An alternative URL commonly used for highlighted stories                         |
| `https://instagram.com/tv/CODE`                            | Similar to reels                                                                 |

### Session management
To retrieve your Instagram cookies, follow these steps:
1. Navigate to *instagram.com* on your browser.
2. Open up Developer Tools, switch to the Network tab, then reload the page.
3. On the list, find the initial request that returns HTML, and inspect its request headers.
4. Copy the value of the `Cookie` header and put it in a text file (e.g. `cookies.txt`).

Example `cookies.txt`:
```
datr=REDACTED; ig_did=REDACTED; csrftoken=REDACTED; mid=REDACTED; ig_nrcb=1; ds_user_id=REDACTED; sessionid=REDACTED; ps_l=1; ps_n=1; rur="REDACTED"; wd=773x818
```

```sh
basketcase session add-cookies ./cookies.txt --set-name "jane.doe"
# New session created (id=1) with 10 cookie(s)
```

This is the recommended method, since we should try to look like a real
browser as much as we can to avoid "automated behavior" warnings.

Alternatively, add a single `sessionid` cookie.
```sh
basketcase session add-cookie "COOKIE_VALUE" --set-name "john.doe"
# New session created (id=1) with one 'sessionid' cookie
```

Specify its identifier when downloading.
```sh
basketcase get -s 1 URL_OR_FILE
```

> List all available sessions with `basketcase session list`.
>
> To disable sessions, use `get --no-session`.
>
> If only one exists, it is treated as the default.
>
> When the instance is closed (`BasketCase.close()`) or the script
> exits, cookies from the HTTP client are saved in the database.
> This keeps your cookies up-to-date.


## User data
Cookies and other application data are kept in your home directory
(i.e. `~/.basketcase`).


## Known limitations
This program relies on the APIs used by the web browser Instagram client,
which can change without a notice.

### Multiple authors, owner is private
Fails to locate a suitable extractor for a standard feed post with multiple
authors, in which the owner - or main author - has a private profile you
cannot see.


## Development setup
This project uses [pipenv](https://pipenv.pypa.io/en/latest/index.html)
for dependency and virtual environment management, so make sure it's
installed. [pipx](https://pipx.pypa.io/stable/) is a convenient tool to manage
your virtual-environment user installations, and it can be used to install pipenv.

### 1. Install build dependencies
These must be installed using the system package manager. The package name
examples listed below are from Debian.

- Python development headers and libraries (e.g. `python3-dev`).
- *lxml* requires `libxml2` and `libxslt`, as
  [documented here](https://lxml.de/installation.html#requirements)
  (e.g. `libxml2-dev libxslt-dev`).
- *cffi* requires *libffi* (e.g. `libffi-dev`).

### 2. Create the environment
`cd` to the project root, then run `pipenv install --dev`.

### Test
To discover and run all tests in this project, activate the project _venv_,
`cd` to the project root and run `python -m unittest`. Test coverage is
still low and needs some effort.

### Package build and upload
First, increment the version in `pyproject.toml`.

Then build the package.
```sh
python -m build
```

If that succeeds, **commit and push** the version change, then **tag** the release.
```sh
git tag -a VERSION_NUMBER -m 'Briefly describe the changes'
git push REMOTE VERSION_NUMBER
```

Finally, publish it.
```sh
python -m twine upload dist/*
```
