Integrate search data into your AI workflow, RAG, fine-tuning, or Rust application using this official SerpApi Rust SDK.
SerpApi supports Google, Google Maps, Google Shopping, Baidu, Yandex, Yahoo, eBay, App Stores, and many more.
To install in your Rust application, update Cargo.toml:
serpapi="1.2.1"Let's start by searching for Coffee on Google:
// search example for google
//
use serpapi::serpapi::Client;
use std::collections::HashMap;
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Read your private API Key from an environment variable.
// Copy/paste from [https://serpapi.com/dashboard] to your shell:
// ```bash
// export API_key="paste_your_private_api_key"
// ```
let api_key = match env::var_os("SERPAPI_KEY") {
Some(v) => v.into_string().unwrap(),
None => panic!("$SERPAPI_KEY environment variable is not set!"),
};
println!("let's initiliaze the client to search on google");
let mut default = HashMap::new();
default.insert("api_key".to_string(), api_key);
default.insert("engine".to_string(), "google".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("q".to_string(), "coffee".to_string());
parameter.insert("engine".to_string(), "google".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let organic_results = results["organic_results"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of organic_results: {}", organic_results.len());
println!(
" - organic_results first result description: {}",
results["organic_results"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["organic_results"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} organic_results", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
let raw = client.html(html_parameter).await.expect("html content");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())
}More examples are available below.
Use search for structured results decoded into a serde_json::Value:
let results = client.search(parameter).await?;Use md for a token-efficient Markdown String optimized for LLMs and AI agents.
It returns clean headings, links and tables behind a YAML frontmatter while using
roughly half the tokens of the JSON output:
let markdown = client.md(parameter).await?;Use html when you need the raw response from the search engine:
let raw_html = client.html(parameter).await?;md and html always force the output format, so any output search parameter is ignored.
Archived results are also available as Markdown with client.search_archive_md(&id).await?.
Learn more about SerpApi Markdown output.
For more information how to build a paramaters HashMap, see serpapi.com documentation.
let mut default = HashMap::<String, String>::new();
default.insert("engine".to_string(), "google".to_string());
default.insert("api_key".to_string(), "your_secret_key".to_string());
let client = Client::new(default).unwrap();
let mut parameter = HashMap::<String, String>::new();
parameter.insert("q".to_string(), "coffee".to_string());
let markdown = client.md(parameter).await.expect("request");It returns the search results formatted as Markdown.
let default = HashMap::<String, String>::new();
let client = Client::new(default).unwrap();
let mut parameter = HashMap::<String, String>::new();
parameter.insert("q".to_string(), "Austin".to_string());
let data = client.location(parameter).await.expect("request");
let locations = data.as_array().unwrap();It returns the first 3 locations matching Austin (Texas, Texas, Rochester).
let mut default = HashMap::<String, String>::new();
default.insert("engine".to_string(), "google".to_string());
default.insert("api_key".to_string(), "your_secret_key".to_string());
let client = Client::new(default).unwrap();
// initialize the search engine
let mut parameter = HashMap::<String, String>::new();
parameter.insert("q".to_string(), "coffee".to_string());
parameter.insert(
"location".to_string(),
"Austin, TX, Texas, United States".to_string(),
);
let initial_results = client.search(parameter).await.expect("request");
let mut id = initial_results["search_metadata"]["id"].to_string();
// remove extra quote " from string convertion
id = id.replace("\"", "");
println!("{}", initial_results["search_metadata"]);
assert_ne!(id, "");
// search in archive
let archived_results = client.search_archive(&id).await.expect("request");
let archive_id = archived_results["search_metadata"]["id"].as_str();
let search_id = initial_results["search_metadata"]["id"].as_str();
println!("{}", archived_results);
assert_eq!(archive_id, search_id);The same archived search is available as Markdown:
let markdown = client.search_archive_md(&id).await.expect("request");let client = Client::new(HashMap::<String, String>::new());
let mut parameter = HashMap::<String, String>::new();
parameter.insert("api_key".to_string(), "your_secret_key".to_string());
let account = client.account(parameter).await.expect("request");It returns your account information.
- Search results as JSON with
search, Markdown withmd, or raw search engine HTML withhtml - Dynamic JSON decoding using Serde JSON
- Asyncronous HTTP request handle method using tokio and reqwest
- Async tests using Tokio
- 1.2.1: Remove
markdown()which called a non-existent endpoint, useclient.md(parameter)andclient.search_archive_md(&id)to return search results formatted as Markdown. - 1.2.0: Add
markdownmethod to return search results formatted as Markdown. - 1.1.0: Always reuse the same client object instead of creating a new one for each search.
- This is a breaking change for the API because the client must be unwrapped in the main function.
# now: 1.1 let client = Client::new(default).unwrap(); # old: 1.0 let client = Client::new(default);
- This is a breaking change for the API because the client must be unwrapped in the main function.
- 1.0.0: Initial release
- https://www.lpalmieri.com/posts/how-to-write-a-rest-client-in-rust-with-reqwest-and-wiremock/
- Serdes JSON
To run an example:
cargo build --example google_searchfile: (examples/google_search.rs)
The keyword google can be replaced by any supported search engine:
- baidu
- bing
- duckduckgo
- yahoo
- yandex
- ebay
- youtube
- walmart
- home_depot
- apple_app_store
- naver
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "bing".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("q".to_string(), "coffee".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let organic_results = results["organic_results"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of organic_results: {}", organic_results.len());
println!(
" - organic_results first result description: {}",
results["organic_results"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["organic_results"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} organic_results", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/bing_search.rs see: https://serpapi.com/bing-search-api
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "baidu".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("q".to_string(), "coffee".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let organic_results = results["organic_results"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of organic_results: {}", organic_results.len());
println!(
" - organic_results first result description: {}",
results["organic_results"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["organic_results"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} organic_results", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/baidu_search.rs see: https://serpapi.com/baidu-search-api
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "yahoo".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("p".to_string(), "coffee".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let organic_results = results["organic_results"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of organic_results: {}", organic_results.len());
println!(
" - organic_results first result description: {}",
results["organic_results"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["organic_results"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} organic_results", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/yahoo_search.rs see: https://serpapi.com/yahoo-search-api
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "youtube".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("search_query".to_string(), "coffee".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let video_results = results["video_results"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of video_results: {}", video_results.len());
println!(
" - video_results first result description: {}",
results["video_results"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["video_results"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} video_results", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/youtube_search.rs see: https://serpapi.com/youtube-search-api
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "walmart".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("query".to_string(), "coffee".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let organic_results = results["organic_results"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of organic_results: {}", organic_results.len());
println!(
" - organic_results first result description: {}",
results["organic_results"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["organic_results"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} organic_results", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/walmart_search.rs see: https://serpapi.com/walmart-search-api
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "ebay".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("_nkw".to_string(), "coffee".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let organic_results = results["organic_results"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of organic_results: {}", organic_results.len());
println!(
" - organic_results first result description: {}",
results["organic_results"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["organic_results"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} organic_results", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/ebay_search.rs see: https://serpapi.com/ebay-search-api
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "naver".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("query".to_string(), "coffee".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let ads_results = results["ads_results"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of ads_results: {}", ads_results.len());
println!(
" - ads_results first result description: {}",
results["ads_results"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["ads_results"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} ads_results", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/naver_search.rs see: https://serpapi.com/naver-search-api
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "home_depot".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("q".to_string(), "table".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let products = results["products"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of products: {}", products.len());
println!(
" - products first result description: {}",
results["products"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["products"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} products", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/home_depot_search.rs see: https://serpapi.com/home-depot-search-api
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "apple_app_store".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("term".to_string(), "coffee".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let organic_results = results["organic_results"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of organic_results: {}", organic_results.len());
println!(
" - organic_results first result description: {}",
results["organic_results"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["organic_results"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} organic_results", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/apple_app_store_search.rs see: https://serpapi.com/apple-app-store
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "duckduckgo".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("q".to_string(), "coffee".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let organic_results = results["organic_results"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of organic_results: {}", organic_results.len());
println!(
" - organic_results first result description: {}",
results["organic_results"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["organic_results"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} organic_results", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/duckduckgo_search.rs see: https://serpapi.com/duckduckgo-search-api
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "google".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("q".to_string(), "coffee".to_string());
parameter.insert("engine".to_string(), "google".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let organic_results = results["organic_results"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of organic_results: {}", organic_results.len());
println!(
" - organic_results first result description: {}",
results["organic_results"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["organic_results"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} organic_results", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/google_search.rs see: https://serpapi.com/search-api
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "google_scholar".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("q".to_string(), "coffee".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let organic_results = results["organic_results"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of organic_results: {}", organic_results.len());
println!(
" - organic_results first result description: {}",
results["organic_results"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["organic_results"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} organic_results", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/google_scholar_search.rs see: https://serpapi.com/google-scholar-api
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "google_autocomplete".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("q".to_string(), "coffee".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let suggestions = results["suggestions"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of suggestions: {}", suggestions.len());
println!(
" - suggestions first result description: {}",
results["suggestions"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["suggestions"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} suggestions", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/google_autocomplete_search.rs see: https://serpapi.com/google-autocomplete-api
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "google_product".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("q".to_string(), "coffee".to_string());
parameter.insert("product_id".to_string(), "4887235756540435899".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let product_results = results["product_results"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of product_results: {}", product_results.len());
println!(
" - product_results first result description: {}",
results["product_results"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["product_results"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} product_results", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/google_product_search.rs see: https://serpapi.com/google-product-api
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "google_reverse_image".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert(
"image_url".to_string(),
"https://i.imgur.com/5bGzZi7.jpg".to_string(),
);
parameter.insert("max_results".to_string(), "1".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let image_sizes = results["image_sizes"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of image_sizes: {}", image_sizes.len());
println!(
" - image_sizes first result description: {}",
results["image_sizes"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["image_sizes"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} image_sizes", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "google_local_services".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("q".to_string(), "electrician".to_string());
parameter.insert("data_cid".to_string(), "6745062158417646970".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let local_ads = results["local_ads"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of local_ads: {}", local_ads.len());
println!(
" - local_ads first result description: {}",
results["local_ads"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["local_ads"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} local_ads", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/google_local_services_search.rs see: https://serpapi.com/google-local-services-api
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "google_maps".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("q".to_string(), "pizza".to_string());
parameter.insert(
"ll".to_string(),
"@40.7455096,-74.0083012,15.1z".to_string(),
);
parameter.insert("type".to_string(), "search".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let local_results = results["local_results"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of local_results: {}", local_results.len());
println!(
" - local_results first result description: {}",
results["local_results"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["local_results"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} local_results", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/google_maps_search.rs see: https://serpapi.com/google-maps-api
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "google_jobs".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("q".to_string(), "coffee".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let jobs_results = results["jobs_results"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of jobs_results: {}", jobs_results.len());
println!(
" - jobs_results first result description: {}",
results["jobs_results"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["jobs_results"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} jobs_results", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/google_jobs_search.rs see: https://serpapi.com/google-jobs-api
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "google_play".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("q".to_string(), "kite".to_string());
parameter.insert("store".to_string(), "apps".to_string());
parameter.insert("max_results".to_string(), "2".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let organic_results = results["organic_results"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of organic_results: {}", organic_results.len());
println!(
" - organic_results first result description: {}",
results["organic_results"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["organic_results"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} organic_results", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/google_play_search.rs see: https://serpapi.com/google-play-api
let mut default = HashMap::new();
default.insert("api_key".to_string(), "your_secret_api_key".to_string());
default.insert("engine".to_string(), "google_images".to_string());
// initialize the search engine
let client = Client::new(default).unwrap();
// let's search for coffee in Austin, TX
let mut parameter = HashMap::new();
parameter.insert("engine".to_string(), "google_images".to_string());
parameter.insert("tbm".to_string(), "isch".to_string());
parameter.insert("q".to_string(), "coffee".to_string());
// copy search parameter for the html search
let mut html_parameter = HashMap::new();
html_parameter.clone_from(¶meter);
// search returns a JSON as serde_json::Value which can be accessed like a HashMap.
println!("waiting...");
let results = client.search(parameter).await?;
let images_results = results["images_results"].as_array().unwrap();
println!("results received");
println!("--- JSON ---");
let status = &results["search_metadata"]["status"];
if status != "Success" {
println!("search failed with status: {}", status);
} else {
println!("search is successfull");
println!(" - number of images_results: {}", images_results.len());
println!(
" - images_results first result description: {}",
results["images_results"][0]
);
// pagination: fetch up to 2 more pages
println!("--- Pagination ---");
let mut next = results["serpapi_pagination"]["next"].as_str().map(String::from);
for page in 2..=3 {
let Some(url) = next else { break };
let page_parameter: HashMap<String, String> =
reqwest::Url::parse(&url)?.query_pairs().into_owned().collect();
let page_results = client.search(page_parameter).await?;
let count = page_results["images_results"].as_array().map_or(0, |r| r.len());
println!(" - page {}: {} images_results", page, count);
next = page_results["serpapi_pagination"]["next"].as_str().map(String::from);
}
// search returns text
println!("--- HTML search ---");
println!(" - raw HTML size {} bytes\n", raw.len());
println!(
" - async search completed with {}\n",
results["search_parameters"]["engine"]
);
}
print!("ok");
Ok(())- source code: examples/google_images_search.rs see: https://serpapi.com/images-results
We love "true open source" and "continuous integration", and Test Drive Development (TDD). We are using RSpec to test our infrastructure around the clock using Github Action to achieve the best QoS (Quality Of Service).
The directory spec/ includes specification which serves the dual purposes of examples and functional tests.
Set your secret API key in your shell before running a test.
export API_KEY="your_secret_key"
cargo testContributions are welcome. Feel to submit a pull request!