booru-rs
An async Rust client for various booru image board APIs.
Features
- Type-safe API — Compile-time checks ensure you use the correct rating types for each booru
- Async/await — Built on tokio and reqwest for efficient async I/O
- Connection pooling — Shared HTTP client with automatic connection reuse
- Proper error handling — No panics, all errors are returned as
Resulttypes - Common
Posttrait — Write generic code that works with any booru site - Async streams — Paginate through results with async iterators
- Image downloads — Download images with progress tracking and concurrent downloads
- Automatic retries — Transient failures are retried with exponential backoff
- Rate limiting — Protect against API throttling
- Response caching — Reduce redundant API calls
- Tag validation — Catch common mistakes before making requests
- Tag autocomplete — Get tag suggestions as users type
Supported Sites
| Site | Client | Tag Limit | Auth Required |
|---|---|---|---|
| Danbooru | DanbooruClient |
2 | No |
| Gelbooru | GelbooruClient |
Unlimited | Yes |
| Safebooru | SafebooruClient |
Unlimited | No |
| Rule34 | Rule34Client |
Unlimited | Yes |
Note: Gelbooru and Rule34 require API credentials. See Authentication below.
Planned:
- Konachan
- 3DBooru
Installation
Add to your Cargo.toml:
[]
= "0.3"
= { = "1", = ["rt-multi-thread", "macros"] }
Selective Features
By default, all booru clients are included. You can enable only the ones you need:
[]
# Only Danbooru support
= { = "0.3", = false, = ["danbooru"] }
# Danbooru + Safebooru
= { = "0.3", = false, = ["danbooru", "safebooru"] }
Available features: danbooru, gelbooru, safebooru, rule34
Quick Start
Use the prelude for convenient imports:
use *;
async
API Examples
Basic Usage
use *;
// Danbooru (limited to 2 tags)
let posts = builder
.tag?
.rating
.limit
.build
.get
.await?;
// Get a specific post by ID
let post = builder
.build
.get_by_id
.await?;
Multiple Tags at Once
use *;
// Gelbooru has no tag limit
let posts = builder
.tags?
.blacklist_tags
.sort
.build
.get
.await?;
Generic Code with the Post Trait
use *;
use Post;
Pagination
use *;
// Get page 5 of results
let posts = builder
.tag?
.page
.limit
.build
.get
.await?;
Async Pagination Stream
use *;
// Stream through all results automatically
let mut stream = builder
.tag?
.limit
.into_post_stream
.max_posts; // Stop after 500 posts
while let Some = stream.next.await
Rate Limiting
use *;
use Duration;
// 2 requests per second
let limiter = new;
for tag in
Response Caching
use *;
let cache = new;
// First call hits the API
let posts = builder
.tag?
.build
.get
.await?;
cache.insert.await;
// Later, check cache first
if let Some = cache..await
Tag Validation
use ;
// Get warnings about potential issues
let result = validate_tag; // Space instead of underscore
if result.has_warnings
// Or get normalized tag directly
let tag = validate_tag_strict?; // Returns "cat_ears"
Tag Autocomplete
Get tag suggestions as the user types:
use *;
// Get tag suggestions for "cat_"
let suggestions = autocomplete.await?;
for tag in suggestions
// Works with all booru clients
let safebooru_tags = autocomplete.await?;
let gelbooru_tags = autocomplete.await?;
Custom HTTP Client
use *;
use ClientBuilder;
let custom_client = builder
.timeout
.build?;
// Use with_client to create a builder with custom HTTP client
let posts = with_client
.tag?
.build
.get
.await?;
Note: Most users won't need a custom HTTP client. The default shared client provides connection pooling and sensible timeouts.
Downloading Images
use *;
use Path;
let posts = builder
.tag?
.limit
.build
.get
.await?;
// Download posts directly
let downloader = new;
for post in &posts
// Download with progress tracking
for post in &posts
// Concurrent downloads (4 at a time)
let results = downloader.download_posts.await;
// Custom options
let downloader = new
.options;
Gelbooru Authentication
Gelbooru requires API credentials for all API requests. To get your credentials:
- Create an account at gelbooru.com
- Go to My Account → Options → API Access Credentials
- Copy your API Key and User ID
use *;
let posts = builder
.set_credentials
.tag?
.build
.get
.await?;
You can also load credentials from environment variables:
use *;
let api_key = var.expect;
let user_id = var.expect;
let posts = builder
.set_credentials
.tag?
.build
.get
.await?;
Rule34 Authentication
Rule34 also requires API credentials:
- Create an account at rule34.xxx
- Go to My Account → Options → API Access Credentials
- Copy your API Key and User ID
use *;
let posts = builder
.set_credentials
.tag?
.build
.get
.await?;
Error Handling
All fallible operations return Result<T, BooruError>:
use *;
match builder.tag?.tag?.tag
Minimum Supported Rust Version
This crate requires Rust 1.92 or later (2024 edition).
License
Licensed under the MIT License.