This release is a pre-release and may not be stable for production use.
youtube-notify
youtube-notify is a small Python library for fetching recent content from a YouTube channel. It prefers the channel RSS feed first and falls back to the YouTube Data API when RSS does not return content. The library returns typed Content models with channel metadata, timestamps, thumbnails, and descriptions.
Features
- RSS-first content retrieval with YouTube API fallback
- Optional YouTube API key and OAuth helpers
- Pydantic models for downstream validation and serialization
- Async-friendly public APIs
- Mocked integration tests for deterministic CI runs
Installation
This repository uses a src/ layout and installs as the youtube_notify package.
git clone https://github.com/jnstockley/youtube-notify.git
cd youtube-notify
uv sync
If you are using another virtual environment tool, install the project from pyproject.toml so the package is available as youtube_notify.
Setup
- Clone the repository.
- Create and activate a Python 3.14 environment.
- Install dependencies with
uv syncor your preferred environment manager. - Set
PYTHONPATH=srcwhen running the library directly from the repository. - If you want to use the YouTube API fallback, provide an API key or OAuth credentials in your own application code.
Usage
The main entry point is youtube_notify.get_content(channel_id, youtube=None).
It tries RSS first and only uses the YouTube API client if RSS returns no content.
Basic usage
import asyncio
from youtube_notify import get_content
async def main() -> None:
content = await get_content("UCxxxxxxxxxxxxxxxxxxxxxx")
for item in content:
print(item.title)
asyncio.run(main())
Fetching a batch with one HTTP client
Pass one httpx.AsyncClient as rss_client to share its connection pool across
all channel requests. The calling application owns and closes the client.
import asyncio
import httpx
from youtube_notify import get_content
async def main() -> None:
channel_ids = ["UCxxxxxxxxxxxxxxxxxxxxxx", "UCyyyyyyyyyyyyyyyyyyyyyy"]
async with httpx.AsyncClient() as client:
results = await asyncio.gather(
*(get_content(channel_id, rss_client=client) for channel_id in channel_ids)
)
asyncio.run(main())
Using a YouTube API key
If you already have a YouTube Data API key, build a client with youtube_notify.youtube.auth.api_key.authenticate() and pass it to youtube_notify.get_content().
import asyncio
from youtube_notify import get_content
from youtube_notify.youtube.auth.api_key import authenticate
async def main() -> None:
youtube = authenticate("YOUR_YOUTUBE_API_KEY")
content = await get_content("UCxxxxxxxxxxxxxxxxxxxxxx", youtube)
for item in content:
print(item.title)
asyncio.run(main())
Using OAuth credentials
If you need OAuth-based access, the OAuth helper can build credentials and refresh them before creating the client.
from youtube_notify.youtube.auth.oauth import authenticate, device_code_flow
creds = device_code_flow("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET")
youtube = authenticate(creds)
Required Environment Variables
The library itself does not require API credentials from environment variables. The only runtime environment settings used by the code are for logging:
LOG_LEVEL: optional, defaults toINFOLOG_DIR: optional, defaults to../logs
The repository also includes sample.env with example values for a wrapper application:
YOUTUBE_API_KEYGOOGLE_CLIENT_IDGOOGLE_CLIENT_SECRET
Those are not read automatically by the library; they are intended for your own application or deployment scripts.
If your application uses the YouTube API path through youtube_notify.youtube.get_content() or
passes a client into youtube_notify.get_content(), you must provide one of the
following sets of credentials in your application layer:
YOUTUBE_API_KEYGOOGLE_CLIENT_IDandGOOGLE_CLIENT_SECRET
Development
Common local commands:
uv run pytest
uv run pytest -m integration
uv run ruff check
uv run ruff format --check
The integration test suite is mocked and does not make live network calls.
Project Structure
src/youtube_notify/content_fetcher.py: top-level RSS-first content fetchersrc/youtube_notify/rss/rss.py: RSS feed fetching and parsingsrc/youtube_notify/youtube/youtube.py: YouTube API fetching and parsingsrc/youtube_notify/youtube/auth/: API key and OAuth helperssrc/youtube_notify/models.py: Pydantic models used across the library
Operational Notes
- The library writes logs to
LOG_DIR/app.log. - If you run the code in a container or read-only environment, set
LOG_DIRto a writable path. - The public APIs are asynchronous, so call them from
asynciocode or wrap them withasyncio.run().
Contributing
Contributions are expected to keep the repository green.
Before opening a pull request:
- All tests must pass.
- Code coverage for updated code should be at least 90%.
- The existing linting steps must pass.
- Any public behavior change should include matching tests.
Recommended validation commands:
uv run pytest
uv run pytest --cov src --cov-branch --cov-report=term-missing
uv run ruff check
uv run ruff format --check
License
This project is licensed under the GNU General Public License v3.0. See the LICENSE file for details.
Release files for youtube-notify 1.1.0b3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| youtube_notify-1.1.0b3.tar.gz | 27.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| youtube_notify-1.1.0b3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 54.7 kB
Release files / youtube_notify-1.1.0b3.tar.gz
| Download URL | youtube_notify-1.1.0b3.tar.gz |
|---|---|
| Size | 27.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8606b6731704973ef45c45c352788801a3b895960de81526da0a00c42b4f279c
|
|
BLAKE2b-256 checksum How to use checksums |
83741ab6695d276b02c0ce0e2da076512eaeeb43228c557d8014f275c2fd1dfd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 26, 2026.
Transparency logRelease files / youtube_notify-1.1.0b3-py3-none-any.whl
| Download URL | youtube_notify-1.1.0b3-py3-none-any.whl |
|---|---|
| Size | 27.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
78cbbea6e674794725e89ec1a75586348ee98e73c96813d74bc74207643d0463
|
|
BLAKE2b-256 checksum How to use checksums |
2de2a869a66389a44462afc4cdb968bdb4c42c1d9fb39ed3fa78c7d3b6eb3431
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 26, 2026.
Transparency log