Metadata-Version: 2.4
Name: ytpaw
Version: 0.1.0
Summary: YouTube search and public statistics client
License-Expression: MIT
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: curl-cffi>=0.13.0
Provides-Extra: test
Requires-Dist: pytest>=7; extra == "test"
Provides-Extra: docs
Requires-Dist: sphinx<10,>=9; python_version >= "3.11" and extra == "docs"
Requires-Dist: sphinx<9,>=6; python_version < "3.11" and extra == "docs"
Requires-Dist: myst-parser<6,>=5; python_version >= "3.11" and extra == "docs"
Requires-Dist: myst-parser<5,>=2; python_version < "3.11" and extra == "docs"
Requires-Dist: shibuya<2027,>=2026.1; python_version >= "3.11" and extra == "docs"
Requires-Dist: shibuya<2026,>=2024; python_version < "3.11" and extra == "docs"
Requires-Dist: sphinx-autodoc-typehints<4,>=3; python_version >= "3.10" and extra == "docs"
Requires-Dist: sphinx-autodoc-typehints<3,>=1; python_version < "3.10" and extra == "docs"
Requires-Dist: sphinx-copybutton<0.6,>=0.5; extra == "docs"
Requires-Dist: sphinx-design<0.8,>=0.7; python_version >= "3.11" and extra == "docs"
Requires-Dist: sphinx-design<0.7,>=0.5; python_version < "3.11" and extra == "docs"
Requires-Dist: sphinxcontrib-mermaid<3,>=2; python_version >= "3.10" and extra == "docs"
Requires-Dist: sphinxcontrib-mermaid<2,>=1; python_version < "3.10" and extra == "docs"

# ytpaw

`ytpaw` is a small Python library for YouTube search and public metadata
collection. It intentionally does not download media, implement SABR or
signature deciphering, or merge audio and video streams.

Shared model field names follow [NAMING_STANDARD.md](NAMING_STANDARD.md), while
YouTube-specific extensions retain their provider-specific meaning.

All Innertube, HTML, and OAuth requests use `curl_cffi` with browser-compatible
TLS handling. Proxy, timeout, retry, OAuth, and PO-token options remain
available through `YouTubeClient`.

## Installation

```bash
pip install ytpaw
```

For development and tests:

```bash
pip install -e ".[test]"
python -m pytest
```

The default suite is network-free. Run the real-YouTube integration suite
explicitly when network access and rate-limit budget are available:

```powershell
$env:YTPAW_RUN_INTEGRATION = "1"
python -m pytest tests/integration -m integration -s
```

For the documentation site:

```bash
uv sync --extra docs
uv run sphinx-build -b html docs docs/_build/html
```

The Russian README is available in [README.ru.md](README.ru.md).

## Quick Start

```python
from ytpaw import YouTubeClient

client = YouTubeClient(min_interval=1.0, retries=3)
video = client.video_stats("https://www.youtube.com/watch?v=dQw4w9WgXcQ")

print(video.title, video.view_count, video.like_count, video.comment_count)
print(client.channel_stats("UC_x5XG1OV2P6uZZ5xm2JYQ"))

for result in client.search("python http client"):
    print(result.result_type, result.id, result.title)
```

## API

- `YouTubeClient.video_stats(url)` returns `VideoStats` for a YouTube video.
- `YouTubeClient.channel_stats(profile_id_or_url)` returns `ChannelStats`.
- `YouTubeClient.channel_videos(profile_id_or_url, limit)` yields available
  video statistics from newest to oldest and follows continuation pages.
- `YouTubeClient.related_videos(url, depth=0)` traverses side-panel
  recommendations breadth-first and yields `RelatedVideo` objects.
- `YouTubeClient.search(query, filters=None)` returns video, channel, and
  playlist `SearchResult` objects.
- `is_video_url(value)`, `is_channel_url(value)`, and `youtube_url_type(value)`
  classify ambiguous input safely before selecting a client method.
- `extract_video_stats()` and `extract_channel_stats()` parse saved responses
  without making network requests.

`channel_videos()` accepts channel IDs, `@handles`, URLs with or without a
scheme, `/channel/ID`, `/@handle`, `/c/name`, `/user/name`, and `/videos`
suffixes. `related_videos(depth=0)` returns direct recommendations only; the
input video itself is never yielded.

Every model keeps the original response in `raw`. The field is hidden from
`repr()` because responses can be large and may contain service metadata.

## Network Context

The client supports `proxy`, `timeout`, `retries`, and `min_interval` for
corporate or rate-limited environments. `visitor_data`, `oauth_token`, and
optional PO-token integration are supported where YouTube requires a specific
request context. These options do not bypass CAPTCHA, authentication,
authorization, access controls, or YouTube policies.

```python
client = YouTubeClient(
    proxy="http://127.0.0.1:8080",
    timeout=20,
    retries=4,
    min_interval=0.5,
    visitor_data="VISITOR_DATA",
    oauth_token="OAUTH_ACCESS_TOKEN",
    language="en",
    region="US",
)
```

The default locale is `en-US` so numeric labels are stable for parsing. Set
`language` and `region` when needed; localized units such as `тыс.`, `Mio.`,
`million`, and `mil` are supported.

## OAuth

```python
client = YouTubeClient(use_oauth=True, allow_oauth_cache=True)
```

The first run starts Google's Device Flow and displays a verification URL and
one-time code. Tokens are refreshed automatically and stored in
`~/.cache/ytpaw/tokens.json` by default. Do not publish or commit this file.
Set `allow_oauth_cache=False` to disable persistence, or pass `oauth_verifier`
for a GUI or custom CLI.

## PO Tokens

```python
from ytpaw import YouTubeClient, generate_po_token

po_token = generate_po_token("dQw4w9WgXcQ")
client = YouTubeClient(
    visitor_data="VISITOR_DATA_FROM_THE_SAME_CONTEXT",
    po_token=po_token,
)
```

Install the optional generator dependencies with `pytubefix` and
`nodejs-wheel-binaries`, or pass a `po_token_verifier` returning
`(visitor_data, po_token)`. Tokens are never fabricated. Missing BotGuard
assets or Node.js results in `RequestError`.

## Windows Encoding

Use UTF-8 output when running the smoke script on Windows:

```powershell
python -X utf8 .\da.py
```

## Limitations and Safety

YouTube changes internal response schemas and applies rate limits. Public
statistics may be incomplete for private, removed, age-restricted, or blocked
content. Live requests are not deterministic.

Do not log or commit access tokens, refresh tokens, bearer headers, visitor
data, PO tokens, or OAuth cache files. Use proxies only when you are authorized
to do so. The project is MIT licensed.
