| Crates.io | serper-sdk |
| lib.rs | serper-sdk |
| version | 0.1.3 |
| created_at | 2025-08-11 20:30:33.493737+00 |
| updated_at | 2025-08-11 20:59:02.011118+00 |
| description | A minimalistic yet ergonomic Rust SDK for the Serper Google Search API |
| homepage | https://github.com/RustSandbox/serper |
| repository | https://github.com/RustSandbox/serper |
| max_upload_size | |
| id | 1790862 |
| size | 173,607 |
A minimalistic yet ergonomic Rust SDK for the Serper Google Search API. Built with a focus on type safety, modularity, and developer experience.
First, sign up at serper.dev to get your free API key. The service offers generous free tier limits.
Add this to your Cargo.toml:
[dependencies]
serper-sdk = "0.1.0"
tokio = { version = "1.0", features = ["full"] }
Basic usage:
use serper_sdk::{SearchService, SearchQuery};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a search service (API key from SERPER_API_KEY env var)
let api_key = std::env::var("SERPER_API_KEY")
.expect("Please set SERPER_API_KEY environment variable");
let service = SearchService::new(api_key)?;
// Build a search query
let query = SearchQuery::new("Hamze Ghalebi CTO at Remolab".to_string())?
.with_location("Paris".to_string())
.with_page(1);
// Execute the search
let response = service.search(&query).await?;
// Process results
for result in response.organic_results() {
println!("{}: {}", result.title, result.link);
}
Ok(())
}
The SDK is organized into focused modules with clear responsibilities:
core - Fundamental types and error handlingsearch - Query construction and response parsinghttp - Transport layer and HTTP client functionalityconfig - Configuration management with environment variable supportutils - Common utilities and validation helpersFor detailed architecture information, see ARCHITECTURE.md.
use serper_sdk::{SearchService, SearchQueryBuilder};
let service = SearchService::new("YOUR_API_KEY".to_string())?;
// Using SearchQueryBuilder
let query = SearchQueryBuilder::new()
.query("Hamze Ghalebi CTO at Remolab")
.location("Paris")
.country("fr")
.language("en")
.page(1)
.num_results(20)
.build()?;
let response = service.search(&query).await?;
let response = service.search_with(|builder| {
builder
.query("Hamze Ghalebi CTO at Remolab")
.location("Paris")
.country("fr")
.page(1)
}).await?;
let queries = vec![
SearchQuery::new("Hamze Ghalebi CTO at Remolab".to_string())?,
SearchQuery::new("Hamze Ghalebi Remolab technology".to_string())?,
SearchQuery::new("Remolab France innovation".to_string())?,
];
// Execute up to 3 searches concurrently
let results = service.search_concurrent(&queries, Some(3)).await?;
for (i, response) in results.iter().enumerate() {
println!("Query {}: {} results", i + 1, response.organic_count());
}
use serper_sdk::{SearchServiceBuilder, config::SdkConfig};
use std::time::Duration;
// Using service builder
// Option 1: Using environment variables (recommended)
let config = SdkConfig::from_env()?;
let service = SearchService::new(config.api_key)?;
// Option 2: Manual configuration
let api_key = std::env::var("SERPER_API_KEY")?;
let service = SearchServiceBuilder::new()
.api_key(api_key)
.timeout(Duration::from_secs(60))
.user_agent("my-app/1.0")
.build()?;
// Using configuration object
let api_key = std::env::var("SERPER_API_KEY")?;
let config = SdkConfig::new(api_key)
.with_timeout(Duration::from_secs(60))
.with_max_concurrent(10)
.with_logging(true);
Set environment variables:
export SERPER_API_KEY="your-api-key"
export SERPER_TIMEOUT_SECS="60"
export SERPER_MAX_CONCURRENT="10"
export SERPER_ENABLE_LOGGING="true"
Then use in your code:
use serper_sdk::config::SdkConfig;
let config = SdkConfig::from_env()?;
// Configuration loaded from environment variables
let response = service.search(&query).await?;
// Direct answers
if let Some(answer_box) = &response.answer_box {
if let Some(answer) = &answer_box.answer {
println!("Direct answer: {}", answer);
}
}
// Knowledge graph
if let Some(kg) = &response.knowledge_graph {
if let Some(title) = &kg.title {
println!("Knowledge graph: {}", title);
}
}
// Organic results
for result in response.organic_results() {
println!("Result: {} ({})",
result.title,
result.domain().unwrap_or("unknown")
);
if result.has_snippet() {
println!(" {}", result.snippet_or_default());
}
}
The SDK provides comprehensive error handling with specific error types:
use serper_sdk::core::SerperError;
match service.search(&query).await {
Ok(response) => {
println!("Success: {} results", response.organic_count());
},
Err(SerperError::InvalidApiKey) => {
println!("Invalid API key provided");
},
Err(SerperError::Api { message }) => {
println!("API error: {}", message);
},
Err(SerperError::Request(e)) => {
println!("Network error: {}", e);
},
Err(SerperError::Json(e)) => {
println!("JSON parsing error: {}", e);
},
Err(e) => {
println!("Other error: {}", e);
}
}
The SDK provides rich response types for different result categories:
pub struct OrganicResult {
pub title: String,
pub link: String,
pub snippet: Option<String>,
pub position: u32,
// ... additional fields
}
pub struct AnswerBox {
pub answer: Option<String>,
pub snippet: Option<String>,
pub title: Option<String>,
pub link: Option<String>,
}
pub struct KnowledgeGraph {
pub title: Option<String>,
pub description: Option<String>,
pub entity_type: Option<String>,
pub website: Option<String>,
// ... additional attributes
}
| Field | Type | Default | Description |
|---|---|---|---|
api_key |
String |
Required | Serper API key |
base_url |
String |
"https://google.serper.dev" |
API base URL |
timeout |
Duration |
30s |
Request timeout |
max_concurrent_requests |
usize |
5 |
Max concurrent requests |
default_headers |
HashMap<String, String> |
{"Content-Type": "application/json"} |
Default headers |
user_agent |
String |
"serper-sdk/{version}" |
User agent string |
enable_logging |
bool |
false |
Enable request/response logging |
| Variable | Description | Default |
|---|---|---|
SERPER_API_KEY |
API key (required) | None |
SERPER_BASE_URL |
API base URL | "https://google.serper.dev" |
SERPER_TIMEOUT_SECS |
Timeout in seconds | 30 |
SERPER_MAX_CONCURRENT |
Max concurrent requests | 5 |
SERPER_USER_AGENT |
Custom user agent | "serper-sdk/{version}" |
SERPER_ENABLE_LOGGING |
Enable logging ("true"/"false") |
false |
Run the test suite:
# Run all tests
cargo test
# Run specific module tests
cargo test search::
cargo test http::
cargo test core::
# Run with output
cargo test -- --nocapture
# Run integration tests
cargo test --test integration_tests
The SDK includes comprehensive tests:
Generate and view the API documentation:
cargo doc --open
Detailed documentation for each module is available in the docs/modules/ directory:
We welcome contributions! Please see our Contributing Guide for details.
git clone https://github.com/RustSandbox/serper.git
cd serper
cargo build
cargo test
cargo fmt --check
cargo clippy -- -D warnings
This project is licensed under the MIT License - see the LICENSE file for details.
See CHANGELOG.md for a detailed history of changes.
cargo doc --openThis SDK is created and maintained by Hamze Ghalebi, CTO at Remolab. Remolab is a technology company focused on innovative software solutions and API integrations.