data-for-seo 0.2.0

Client library for the DataForSEO API v3 (SERP, Keywords Data, Labs, Backlinks, OnPage, and more)
Documentation

data-for-seo

crates.io docs.rs license

data-for-seo is a Rust client library for the DataForSEO API v3. It covers every API domain of v3 with typed request/response models, while staying resilient to API changes (unknown fields and item types never break deserialization).

[dependencies]
data-for-seo = "0.2"

Quick start

use data_for_seo::{DataForSeoClient, BacklinksApiSummaryPost};

#[tokio::main]
async fn main() -> Result<(), data_for_seo::error::DataForSeoError> {
    let client = DataForSeoClient::new("login", "password");

    let response = client
        .backlinks()
        .summary(vec![BacklinksApiSummaryPost::new("https://example.com/")])
        .await?;

    for result in response.results() {
        println!("backlinks: {:?}", result.backlinks);
    }
    Ok(())
}

The client is organized by API domain, mirroring the DataForSEO documentation:

client.serp().google()            client.dataforseo_labs().google()
client.serp().bing()              client.dataforseo_labs().amazon()
client.serp().youtube()           client.dataforseo_labs().apple()
client.keywords_data().google_ads()
client.keywords_data().bing()     client.merchant().amazon()
client.on_page()                  client.merchant().google()
client.backlinks()                client.app_data().google()
client.domain_analytics().technologies()
client.content_analysis()         client.business_data().google()
client.content_generation()       client.ai_optimization().chat_gpt()

Task-based endpoints

Many endpoints follow DataForSEO's task flow (task_post → tasks_ready → task_get):

use data_for_seo::{DataForSeoClient, SerpApiGoogleOrganicTaskPostRequest};

async fn example(client: &DataForSeoClient) -> Result<(), data_for_seo::error::DataForSeoError> {
    let mut request = SerpApiGoogleOrganicTaskPostRequest::new("ja".to_string(), 2392);
    request.keyword = "seo".to_string();

    let posted = client.serp().google().organic_task_post(vec![request]).await?;
    let task_id = &posted.tasks()[0].id;

    // ... poll tasks_ready, then:
    let result = client.serp().google().organic_task_get_advanced(task_id).await?;
    for page in result.results() {
        for item in page.items() {
            println!("{:?}", item);
        }
    }
    Ok(())
}

Response helpers

Every call returns DataForSeoApiResponse<T> (= Result<DataForSeoApiResponseData<T>, DataForSeoError>). The response data exposes:

  • response.tasks() — all tasks as a slice (never panics on null)
  • response.results() / response.into_results() — iterate every result of every task
  • response.first_result() — first result across all tasks
  • task.results(), task.is_success(), task.task_status() — per-task access

Credentials

Pass your API login and password directly (DataForSeoClient::new), or read them from the DATAFORSEO_LOGIN / DATAFORSEO_PASSWORD environment variables:

use data_for_seo::DataForSeoClient;

let client = DataForSeoClient::from_env()?; // DATAFORSEO_LOGIN / DATAFORSEO_PASSWORD

Sandbox

DataForSEO's sandbox is free and returns mock data:

use data_for_seo::DataForSeoClient;
let client = DataForSeoClient::new("login", "password").sandbox();

Error handling

DataForSeoError implements std::error::Error and distinguishes:

  • Api — the API returned an error envelope (status_code, status_message, see error codes)
  • Http — a non-JSON HTTP failure
  • System — transport or deserialization failure

Supported API domains (all v3 domains)

Domain Coverage
SERP Google (Organic, AI Mode, Maps, Local Finder, News, Events, Images, Jobs, Autocomplete, Dataset Search/Info, Ads Advertisers, Ads Search), Bing, YouTube (Organic, Video Info/Subtitles/Comments), Baidu, Yahoo, Seznam, Naver
Keywords Data Google Ads (Search Volume, Keywords For Site/Keywords, Ad Traffic), Bing (Search Volume, Keyword Performance, Search Volume History, Keyword Suggestions For URL, Audience Estimation, ...), Google Trends, DataForSEO Trends, Clickstream Data
DataForSEO Labs Google (Ranked Keywords, Keyword Ideas/Suggestions, Related Keywords, Competitors, Domain/Page Intersection, Traffic Estimation, Search Intent, Historical data, ...), Amazon, Apple App Store
Backlinks Summary, History, Backlinks, Anchors, Domain Pages, Referring Domains/Networks, Competitors, Intersections, Timeseries, Bulk endpoints, Index
OnPage Task Post, Summary, Pages, Resources, Links, Duplicate Tags/Content, Redirect Chains, Non-Indexable, Waterfall, Keyword Density, Microdata, Raw HTML, Screenshot, Content Parsing, Instant Pages, Lighthouse
Domain Analytics Technologies (full), Whois
Content Analysis Search, Summary, Sentiment Analysis, Rating Distribution, Phrase/Category Trends
Content Generation Generate (Text/Meta Tags/Sub Topics), Paraphrase, Check Grammar, Text Summary
Merchant Amazon (Products, ASIN, Sellers), Google Shopping (Products, Sellers, Product Spec/Info)
App Data Google Play, Apple App Store (App Searches, App List, App Info, App Reviews)
Business Data Google (My Business, Hotels, Reviews, Q&A), Trustpilot, Tripadvisor, Social Media, Business Listings
AI Optimization AI Keyword Data, LLM Mentions, LLM Responses (ChatGPT, Claude, Gemini, Perplexity), LLM Scraper

A few endpoints whose response schema is not documented return serde_json::Value so the raw data is still accessible.

Testing

cargo test                 # offline deserialization tests (no credentials needed)
cargo test -- --ignored    # live API tests; requires .env with ID and PASSWORD

License

MIT