A3S Docs
A3S Search

Quick Start

Get up and running with A3S Search in any supported language

Quick Start

Installation

[dependencies]
a3s-search = "0.8"
tokio = { version = "1", features = ["full"] }

Headless browser engines (Google, Baidu, Bing China) are enabled by default. HTTP-only:

a3s-search = { version = "0.7", default-features = false }
pip install a3s-search

Python 3.9–3.13. Pre-built wheels for Linux (glibc/musl), macOS, and Windows.

npm install @a3s-lab/search

Node.js 16+. Native binary for Linux, macOS, and Windows (x64/arm64).

# Install
brew tap a3s-lab/tap https://github.com/A3S-Lab/homebrew-tap
brew install a3s-search

# Update
brew update && brew upgrade a3s-search

# Uninstall
brew uninstall a3s-search
brew untap a3s-lab/tap   # optional: remove the tap

macOS and Linux. Installs the a3s-search CLI binary. See CLI for usage.

Basic Usage

1. Create and Configure

use a3s_search::{Search, SearchQuery};
use a3s_search::engines::{DuckDuckGo, Brave, Wikipedia};

let mut search = Search::new();
search.add_engine(DuckDuckGo::new());
search.add_engine(Brave::new());
search.add_engine(Wikipedia::new());
let query = SearchQuery::new("rust programming");
let results = search.search(query).await?;

for result in results.items().iter().take(10) {
    println!("{}: {}", result.title, result.url);
    println!("  Score: {:.2}, Engines: {:?}", result.score, result.engines);
}

3. Error Handling

Each engine runs independently — one failure doesn't block others:

for (engine, error) in results.errors() {
    eprintln!("Engine '{}' failed: {}", engine, error);
}
from a3s_search import A3SSearch

search = A3SSearch()

# Default engines: DuckDuckGo + Wikipedia
response = await search.search("rust programming")

for r in response.results:
    print(f"{r.title}: {r.url} (score: {r.score})")

print(f"{response.count} results in {response.duration_ms}ms")
import { A3SSearch } from '@a3s-lab/search';

const search = new A3SSearch();

// Default engines: DuckDuckGo + Wikipedia
const response = await search.search('rust programming');

for (const r of response.results) {
  console.log(`${r.title}: ${r.url} (score: ${r.score})`);
}

console.log(`${response.count} results in ${response.durationMs}ms`);

Search with Options

use a3s_search::{SearchQuery, SafeSearch, TimeRange, EngineCategory};

let query = SearchQuery::new("rust async")
    .with_language("en-US")
    .with_safesearch(SafeSearch::Moderate)
    .with_page(1)
    .with_time_range(TimeRange::Month)
    .with_categories(vec![EngineCategory::General])
    .with_engines(vec!["ddg".into(), "brave".into(), "bing".into()]);
response = await search.search("rust async",
    engines=["ddg", "brave", "bing"],
    limit=5,
    timeout=15,
)
const response = await search.search('rust async', {
  engines: ['ddg', 'brave', 'bing'],
  limit: 5,
  timeout: 15,
});

Chinese Search Engines

use a3s_search::engines::{Sogou, So360};

let mut search = Search::new();
search.add_engine(Sogou::new());
search.add_engine(So360::new());

let results = search.search(SearchQuery::new("Rust 编程语言")).await?;
response = await search.search("Rust 编程语言", engines=["sogou", "360"])
const response = await search.search('Rust 编程语言', {
  engines: ['sogou', '360'],
});

With Proxy Pool (Rust)

Rotate proxies per request for anti-crawler protection:

use std::sync::Arc;
use a3s_search::{Search, SearchQuery, PooledHttpFetcher, PageFetcher};
use a3s_search::engines::{DuckDuckGo, DuckDuckGoParser};
use a3s_search::proxy::{ProxyPool, ProxyConfig, ProxyProtocol, ProxyStrategy};

let pool = Arc::new(ProxyPool::with_proxies(vec![
    ProxyConfig::new("proxy1.example.com", 8080),
    ProxyConfig::new("proxy2.example.com", 8080)
        .with_protocol(ProxyProtocol::Socks5),
]).with_strategy(ProxyStrategy::RoundRobin));

let fetcher: Arc<dyn PageFetcher> = Arc::new(PooledHttpFetcher::new(Arc::clone(&pool)));
let mut search = Search::new();
search.add_engine(DuckDuckGo::with_fetcher(DuckDuckGoParser, fetcher));

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

// Toggle at runtime (thread-safe via AtomicBool)
pool.set_enabled(false);  // direct connection
pool.set_enabled(true);   // re-enable rotation

See Proxy for dynamic providers and SDK usage.

With Health Monitor (Rust)

Automatically suspend engines after repeated failures:

use a3s_search::{Search, HealthConfig};
use std::time::Duration;

let mut search = Search::with_health_config(HealthConfig {
    max_failures: 3,
    suspend_duration: Duration::from_secs(120),
});
search.add_engine(DuckDuckGo::new());
search.add_engine(Brave::new());

See Configuration for HCL config files.

On this page