REDD
Reddit Extraction and Data Dumper
A modern, async-ready Python library for extracting Reddit data. No API keys required.
https://github.com/user-attachments/assets/2c377e2a-ac44-4596-89cd-60ce45ce3f4c
Table of Contents
- Features
- Installation
- Quick Start
- API Reference
- Architecture
- Examples
- Contributing
- Disclaimer
- License
1. Features
- No API keys — uses Reddit's public
.jsonendpoints. - Sync and async — choose
ReddorAsyncRedddepending on your stack. - Typed models — frozen dataclasses instead of raw dictionaries.
- Hexagonal architecture — swap HTTP adapters without touching business logic.
- Auto-pagination — fetch hundreds of posts with a single call.
- User-Agent rotation — built-in rotation to reduce ban risk.
- Proxy support — pass a proxy URL and scrape at scale.
- Throttling — configurable random sleep between paginated requests.
2. Installation
With uv (recommended):
uv add redd
With pip:
pip install redd
For async support (requires httpx):
uv add redd httpx
3. Quick Start
3.1. Synchronous usage
from redd import Redd, Category, TimeFilter
with Redd() as r:
# Search Reddit
results = r.search("Python programming", limit=5)
for item in results:
print(f" {item.title}")
# Fetch top posts from a subreddit
posts = r.get_subreddit_posts(
"Python",
limit=10,
category=Category.TOP,
time_filter=TimeFilter.WEEK,
)
for post in posts:
print(f" [{post.score:>5}] {post.title}")
# Get full post details with comments
detail = r.get_post("/r/Python/comments/abc123/example_post/")
print(f" {detail.title} -- {len(detail.comments)} comments")
# Scrape user activity
items = r.get_user("spez", limit=10)
for item in items:
print(f" [{item.kind}] {item.title or item.body[:80]}")
3.2. Asynchronous usage
import asyncio
from redd import AsyncRedd
async def main():
async with AsyncRedd() as r:
results = await r.search("machine learning", limit=5)
for item in results:
print(item.title)
asyncio.run(main())
3.3. Configuration
r = Redd(
proxy="http://user:pass@host:port", # Optional proxy
timeout=15.0, # Request timeout in seconds
rotate_user_agent=True, # Rotate UA per request
throttle=(1.0, 3.0), # Random sleep range between pages
)
4. API Reference
4.1. Clients
| Class | Description |
|---|---|
Redd |
Synchronous client (requests) |
AsyncRedd |
Asynchronous client (httpx) |
Both clients support context managers and expose the same API surface.
4.2. Methods
| Method | Description |
|---|---|
search(query, *, limit, sort, after, before) |
Search all of Reddit |
search_subreddit(subreddit, query, *, limit, sort, after, before) |
Search within a subreddit |
get_post(permalink) |
Get full post details and comment tree |
get_user(username, *, limit) |
Get a user's recent activity |
get_subreddit_posts(subreddit, *, limit, category, time_filter) |
Fetch subreddit listings |
get_user_posts(username, *, limit, category, time_filter) |
Fetch a user's submitted posts |
download_image(image_url, *, output_dir) |
Download an image |
close() |
Release HTTP resources |
4.3. Models
All models are frozen dataclasses.
| Model | Fields |
|---|---|
SearchResult |
title, url, description, subreddit |
PostDetail |
title, author, body, score, url, subreddit, created_utc, num_comments, comments |
Comment |
author, body, score, replies |
SubredditPost |
title, author, permalink, score, num_comments, created_utc, subreddit, url, image_url, thumbnail_url |
UserItem |
kind, subreddit, url, created_utc, title, body |
4.4. Enums
| Enum | Values |
|---|---|
Category |
HOT, TOP, NEW, RISING |
UserCategory |
HOT, TOP, NEW |
TimeFilter |
HOUR, DAY, WEEK, MONTH, YEAR, ALL |
SortOrder |
RELEVANCE, HOT, TOP, NEW, COMMENTS |
4.5. Exceptions
| Exception | Description |
|---|---|
ReddError |
Base exception for all REDD errors |
HttpError |
HTTP request failed after retries |
ParseError |
Reddit's JSON could not be parsed into domain models |
NotFoundError |
Requested resource does not exist |
5. Architecture
REDD follows hexagonal architecture (ports and adapters), separating business logic from I/O concerns:
graph LR
subgraph Public API
A["Redd (sync)"]
B["AsyncRedd (async)"]
end
subgraph Core
C["Parsing Layer"]
D["Domain Models"]
E["Enums"]
end
subgraph Ports
F["HttpPort"]
G["AsyncHttpPort"]
end
subgraph Adapters
H["RequestsHttpAdapter"]
I["HttpxAsyncAdapter"]
end
A --> C
B --> C
C --> D
C --> E
A --> F
B --> G
F -.implements.-> H
G -.implements.-> I
H --> J["reddit.com"]
I --> J
Directory layout
src/redd/
├── __init__.py # Public API surface
├── _client.py # Sync client (Redd)
├── _async_client.py # Async client (AsyncRedd)
├── _parsing.py # JSON to domain model parsing (I/O-free)
├── _exceptions.py # Error hierarchy
│
├── domain/ # Pure domain layer
│ ├── models.py # Frozen dataclasses
│ └── enums.py # Type-safe enumerations
│
├── ports/ # Abstract interfaces
│ └── http.py # HttpPort and AsyncHttpPort protocols
│
└── adapters/ # Concrete implementations
├── http_sync.py # requests-based adapter
└── http_async.py # httpx-based adapter
The parsing module has no I/O dependencies. Clients interact with the HTTP layer exclusively through protocol-based ports, making it straightforward to swap adapters, mock dependencies in tests, or add new transports.
6. Examples
See the examples/ directory for runnable scripts.
Fetch hot posts from a subreddit (subreddit_hot_posts.py):
from redd import Category, Redd
with Redd() as r:
posts = r.get_subreddit_posts("brdev", limit=10, category=Category.HOT)
for i, post in enumerate(posts, 1):
print(f"{i:>2}. [{post.score:>5}] {post.title}")
print(f" by u/{post.author} — {post.num_comments} comments")
print(f" {post.url}")
print()
Sample output:
1. [ 91] Qual o plano B de vocês caso a área piore muito?
by u/Spiritual_Pangolin18 — 185 comments
https://www.reddit.com/r/brdev/comments/1rnytuh/...
2. [ 83] Fuçando minhas coisas, encontrei um código de 600 linhas em Portugol
by u/Dramatic-Revenue-802 — 7 comments
https://www.reddit.com/r/brdev/comments/1ro269a/...
7. Contributing
Contributions are welcome. Please read CONTRIBUTING.md for guidelines on setting up the project, running tests, and submitting changes.
8. Disclaimer
Use responsibly. Reddit may rate-limit or ban IPs that make excessive requests. Consider using rotating proxies for large-scale scraping.
9. License
MIT. See LICENSE for details.
Copyright (c) 2025 Elias Biondo
Metadata
Release files for redd 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| redd-0.2.1.tar.gz | 48.6 kB | Without provenance | Details for redd-0.2.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| redd-0.2.1-py3-none-any.whl | Python 3 | none | any | Details for redd-0.2.1-py3-none-any.whl |
Total release size: 70.9 kB
Release files / redd-0.2.1.tar.gz
| Download URL | redd-0.2.1.tar.gz |
|---|---|
| Size | 48.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
90246b3ccb512eaafe8ca0158bd067acd7a718f567b2df2356306e7cee1788b5
|
|
BLAKE2b-256 checksum How to use checksums |
50683173fa89ce6013fc9d2b73257a9083b07f5b23dbb8e2174f9d1240bc7d57
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.21 {"installer":{"name":"uv","version":"0.12.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / redd-0.2.1-py3-none-any.whl
| Download URL | redd-0.2.1-py3-none-any.whl |
|---|---|
| Size | 22.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7624e4928aecf99898c4c7d117c8b862b8a206a8a9859b2e5e98c64eff138c5b
|
|
BLAKE2b-256 checksum How to use checksums |
efe1db774a65def2d11944c3c9f8d9ca43ad28a865242e2d4a0a5a45ce9b81af
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.21 {"installer":{"name":"uv","version":"0.12.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for redd 0.2.1
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.