SerpClient

Struct SerpClient 

Source
pub struct SerpClient { /* private fields */ }
Expand description

The main SerpAPI client for executing search requests.

SerpClient is the primary interface for interacting with the SerpAPI service. It manages authentication, HTTP connections, retry logic, and response parsing. The client is thread-safe and can be shared across multiple async tasks.

§Design Philosophy

The client is designed with the following principles:

  • Ergonomic API: Intuitive method chaining and builder patterns
  • Robust error handling: Comprehensive error types with actionable information
  • Production-ready: Built-in retry logic, rate limiting, and observability
  • Performance: Connection pooling, async I/O, and efficient serialization

§Connection Management

The client maintains an internal connection pool for efficient HTTP communication. Connections are reused across requests to minimize latency and resource usage.

§Authentication

Authentication is handled via API key, which can be provided through:

  1. Direct configuration via the builder
  2. Environment variable SERP_API_KEY

§Error Handling

The client automatically handles common error scenarios:

  • Network errors: Retried with exponential backoff
  • Rate limiting: Respects Retry-After headers
  • Server errors: 5xx responses trigger automatic retries
  • Client errors: 4xx responses return immediately with detailed error info

§Examples

let client = SerpClient::new("your-api-key")?;

let results = client.search(
    SearchQuery::new("rust async programming")
        .limit(20)?
).await?;

for result in results.organic_results.unwrap_or_default() {
    println!("{}: {}", result.title, result.link);
}

§With Error Handling

match client.search(SearchQuery::new("query")).await {
    Ok(results) => {
        // Process results
    }
    Err(SerpError::RateLimited { retry_after }) => {
        println!("Rate limited, retry after {} seconds", retry_after);
    }
    Err(e) => {
        eprintln!("Search failed: {}", e);
    }
}

Implementations§

Source§

impl SerpClient

Source

pub fn builder() -> SerpClientBuilder

Creates a new client builder for configuration.

This is the recommended way to create a client instance, as it provides full control over configuration options.

§Examples
use serp_sdk::SerpClient;

let client = SerpClient::builder()
    .api_key("your-api-key")
    .build()?;
Source

pub fn new(api_key: impl Into<String>) -> SerpResult<Self>

Creates a new client with just an API key using default settings.

This is a convenience method for simple use cases. For more control over configuration, use SerpClient::builder().

§Arguments
  • api_key - The SerpAPI authentication key
§Examples
let client = SerpClient::new("your-api-key")?;
§Errors

Returns SerpError::InvalidParameter if the API key is empty.

Source

pub async fn search( &self, query: SearchQueryBuilder, ) -> SerpResult<SearchResults>

Executes a search query asynchronously.

This is the main method for performing searches. It handles:

  • Query parameter validation
  • HTTP request construction
  • Automatic retry on transient failures
  • Rate limiting detection and respect
  • Response parsing and validation
§Arguments
  • query - A configured search query builder
§Returns

Returns Result<SearchResults> containing:

  • Organic search results
  • Knowledge graph data
  • Answer boxes
  • Related searches
  • And more specialized result types
§Examples
let results = client.search(
    SearchQuery::new("rust programming")
        .language("en")
        .limit(20)?
).await?;

println!("Found {} organic results",
    results.organic_results.as_ref().map_or(0, |r| r.len()));
§Errors
Source

pub fn api_key_masked(&self) -> String

Returns a masked version of the API key for logging.

This method is useful for debugging and logging without exposing the full API key. It shows the first 4 and last 4 characters.

§Examples
let client = SerpClient::new("abcd1234efgh5678")?;
assert_eq!(client.api_key_masked(), "abcd***5678");
Source

pub fn is_configured(&self) -> bool

Checks if the client is properly configured.

A client is considered configured if it has a non-empty API key.

§Examples
let client = SerpClient::new("api-key")?;
assert!(client.is_configured());
Source§

impl SerpClient

Source

pub fn search_stream( &self, base_query: SearchQueryBuilder, config: StreamConfig, ) -> Pin<Box<dyn Stream<Item = SerpResult<SearchResults>> + Send + '_>>

Stream paginated search results

This method returns a stream that yields SearchResults for each page. It automatically handles pagination by incrementing the start parameter.

§Example
use futures::StreamExt;
use serp_sdk::{SerpClient, SearchQuery, StreamConfig};

let mut stream = client.search_stream(
    SearchQuery::new("rust programming"),
    StreamConfig::default()
);

while let Some(result) = stream.next().await {
    match result {
        Ok(page) => println!("Got {} results", page.organic_results.as_ref().map_or(0, |r| r.len())),
        Err(e) => eprintln!("Error: {}", e),
    }
}
Source

pub fn organic_results_stream( &self, base_query: SearchQueryBuilder, config: StreamConfig, ) -> Pin<Box<dyn Stream<Item = SerpResult<OrganicResult>> + Send + '_>>

Stream individual organic results across multiple pages

This method flattens the paginated results into a stream of individual organic search results, making it easier to process results one by one.

Source

pub fn search_until<F>( &self, base_query: SearchQueryBuilder, config: StreamConfig, predicate: F, ) -> Pin<Box<dyn Stream<Item = SerpResult<SearchResults>> + Send + '_>>
where F: FnMut(&SearchResults) -> bool + Send + 'static,

Stream results until a condition is met

This method continues fetching pages until the provided predicate returns true or an error occurs. Useful for searching until you find a specific result.

Source

pub async fn search_all( &self, base_query: SearchQueryBuilder, config: StreamConfig, ) -> SerpResult<Vec<OrganicResult>>

Collect all results from multiple pages into a single vector

This method fetches all pages and combines the organic results into a single vector. Use with caution for large result sets.

Trait Implementations§

Source§

impl Clone for SerpClient

Source§

fn clone(&self) -> SerpClient

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,