| Crates.io | surfai |
| lib.rs | surfai |
| version | 0.1.2 |
| created_at | 2025-07-05 12:01:11.184197+00 |
| updated_at | 2025-07-17 09:30:06.011863+00 |
| description | Advanced browser automation library with human-like interactions and stealth capabilities for web scraping |
| homepage | https://github.com/DevMaan707/surfai |
| repository | https://github.com/DevMaan707/surfai |
| max_upload_size | |
| id | 1739001 |
| size | 243,297 |
A powerful Rust-based browser automation framework with human-like behavior simulation and stealth capabilities. Built on top of chromiumoxide with advanced scripting, element interaction, and MCP (Model Context Protocol) server integration.
Add this to your Cargo.toml:
[dependencies]
surfai = "0.1.2"
tokio = { version = "1.0", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
use surfai::*;
#[tokio::main]
async fn main() -> Result> {
// Create a new browser instance
let browser = BrowserManager::new(false).await?;
let page = browser.new_page("https://google.com").await?;
// Initialize components
let scraper = PageScraper::new(page.clone());
let interactor = ElementInteractor::new(page.clone());
// Scrape page data
let page_data = scraper.scrape_page().await?;
println!("Page title: {}", page_data.title);
// Find interactive elements
let elements = interactor.find_interactable_elements().await?;
println!("Found {} interactive elements", elements.len());
// Take screenshot
let screenshot = scraper.take_screenshot().await?;
std::fs::write("screenshot.png", screenshot)?;
browser.close().await?;
Ok(())
}
use surfai::*;
#[tokio::main]
async fn main() -> Result> {
// Create stealth browser
let browser = BrowserManager::new_stealth_browser(false).await?;
let page = browser.new_page("https://google.com").await?;
let human = HumanInteractor::new(page.clone());
// Apply stealth settings
human.apply_stealth().await?;
human.setup_session().await?;
// Perform human-like search
let search_query = "rust programming language";
human.search_with_realistic_pattern(search_query).await?;
human.submit_search().await?;
// Wait for results and extract
human.wait_for_results(30).await?;
let results = human.extract_search_results().await?;
println!("Found {} results", results.len());
for (i, result) in results.iter().enumerate().take(5) {
println!("{}. {}", i + 1, result.get("title").unwrap_or(&"No title".to_string()));
println!(" Link: {}", result.get("link").unwrap_or(&"No link".to_string()));
}
browser.close().await?;
Ok(())
}
The framework includes a built-in MCP (Model Context Protocol) server for seamless AI agent integration.
use surfai::mcp::MCPBrowserServer;
#[tokio::main]
async fn main() -> Result> {
let server = MCPBrowserServer::new();
// Handle MCP requests
let request = MCPRequest {
id: "1".to_string(),
method: "tools/list".to_string(),
params: serde_json::json!({}),
};
let response = server.handle_request(request).await;
println!("MCP Response: {:?}", response);
Ok(())
}
The MCP server provides the following tools for AI agents:
create_browser_sessionCreates a new browser session with optional stealth mode.
Parameters:
headless (boolean, default: true): Run browser in headless modestealth (boolean, default: false): Enable stealth anti-detection featuresExample:
{
"name": "create_browser_session",
"arguments": {
"headless": false,
"stealth": true
}
}
navigate_to_urlNavigate to a specific URL in an existing session.
Parameters:
session_id (string, required): Browser session IDurl (string, required): Target URLExample:
{
"name": "navigate_to_url",
"arguments": {
"session_id": "uuid-session-id",
"url": "https://google.com"
}
}
search_googlePerform a Google search with human-like behavior patterns.
Parameters:
session_id (string, required): Browser session IDquery (string, required): Search queryExample:
{
"name": "search_google",
"arguments": {
"session_id": "uuid-session-id",
"query": "rust programming language"
}
}
get_page_elementsExtract all interactable elements from the current page.
Parameters:
session_id (string, required): Browser session IDelement_types (array, optional): Specific element types to filterExample:
{
"name": "get_page_elements",
"arguments": {
"session_id": "uuid-session-id",
"element_types": ["input", "button", "a"]
}
}
click_elementClick on an element with human-like mouse movements.
Parameters:
session_id (string, required): Browser session IDselector (string, required): CSS selector for the elementExample:
{
"name": "click_element",
"arguments": {
"session_id": "uuid-session-id",
"selector": "button[type='submit']"
}
}
type_textType text into an element with realistic human typing patterns.
Parameters:
session_id (string, required): Browser session IDselector (string, required): CSS selector for the input elementtext (string, required): Text to typeExample:
{
"name": "type_text",
"arguments": {
"session_id": "uuid-session-id",
"selector": "input[name='q']",
"text": "Hello world"
}
}
scrape_pageExtract all data from the current page including title, content, links, images, and forms.
Parameters:
session_id (string, required): Browser session IDExample:
{
"name": "scrape_page",
"arguments": {
"session_id": "uuid-session-id"
}
}
take_screenshotCapture a screenshot of the current page.
Parameters:
session_id (string, required): Browser session IDExample:
{
"name": "take_screenshot",
"arguments": {
"session_id": "uuid-session-id"
}
}
close_sessionClose a browser session and clean up resources.
Parameters:
session_id (string, required): Browser session IDExample:
{
"name": "close_session",
"arguments": {
"session_id": "uuid-session-id"
}
}
create_browser_session to initialize a browsernavigate_to_url to go to target websitesclick_element, type_text, or search_google for interactionsscrape_page, get_page_elements, or take_screenshot for data extractionclose_session to properly close the browseruse surfai::mcp::*;
async fn ai_agent_workflow() -> Result> {
let server = MCPBrowserServer::new();
// Step 1: Create browser session
let create_request = MCPRequest {
id: "1".to_string(),
method: "tools/call".to_string(),
params: serde_json::json!({
"name": "create_browser_session",
"arguments": {
"headless": false,
"stealth": true
}
}),
};
let response = server.handle_request(create_request).await;
let session_id = response.result.unwrap()["session_id"].as_str().unwrap();
// Step 2: Perform Google search
let search_request = MCPRequest {
id: "2".to_string(),
method: "tools/call".to_string(),
params: serde_json::json!({
"name": "search_google",
"arguments": {
"session_id": session_id,
"query": "AI automation tools"
}
}),
};
let search_response = server.handle_request(search_request).await;
println!("Search results: {:?}", search_response.result);
// Step 3: Take screenshot
let screenshot_request = MCPRequest {
id: "3".to_string(),
method: "tools/call".to_string(),
params: serde_json::json!({
"name": "take_screenshot",
"arguments": {
"session_id": session_id
}
}),
};
let screenshot_response = server.handle_request(screenshot_request).await;
// Step 4: Close session
let close_request = MCPRequest {
id: "4".to_string(),
method: "tools/call".to_string(),
params: serde_json::json!({
"name": "close_session",
"arguments": {
"session_id": session_id
}
}),
};
server.handle_request(close_request).await;
Ok(())
}
BrowserManagerMain browser management interface.
Methods:
new(headless: bool) -> BrowserResult: Create standard browsernew_stealth_browser(headless: bool) -> BrowserResult: Create stealth browsernew_page(url: &str) -> BrowserResult: Create new pageclose(self) -> BrowserResult: Close browserHumanInteractorHuman-like interaction simulation.
Key Methods:
apply_stealth() -> BrowserResult: Apply stealth settingstype_human(selector: &str, text: &str) -> BrowserResult: Human-like typingclick_human(selector: &str) -> BrowserResult: Human-like clickingsearch_with_realistic_pattern(query: &str) -> BrowserResult: Realistic searchextract_search_results() -> BrowserResult>>: Extract resultsElementInteractorElement detection and interaction.
Key Methods:
get_all_elements() -> BrowserResult>: Get all elementsget_interactable_elements() -> BrowserResult>: Get interactive elementslabel_elements(tags: Option>) -> BrowserResult>: Label elementsclick_element(selector: &str) -> BrowserResult: Click elementtype_text(selector: &str, text: &str) -> BrowserResult: Type textPageScraperWeb page data extraction.
Key Methods:
scrape_page() -> BrowserResult: Scrape all page datatake_screenshot() -> BrowserResult>: Take screenshotextract_links() -> BrowserResult>: Extract linksextract_images() -> BrowserResult>: Extract imagesThe stealth browser includes comprehensive anti-detection features:
let browser = BrowserManager::new_stealth_browser(false).await?;
Stealth Features:
Customize human-like behavior:
let human = HumanInteractor::new(page);
// Configure timing patterns
human.random_delay(1000, 2000).await; // Random delay between 1-2 seconds
human.simulate_reading_delay("Sample text").await; // Reading-based delay
human.simulate_hesitation().await; // Simulate user hesitation
The examples/ directory contains comprehensive usage examples:
basic_usage.rs: Basic browser automationgoogle_search.rs: Google search automationhuman_google_search.rs: Human-like Google searchlabel_elements.rs: Element labeling and interactionRun examples with:
cargo run --example basic_usage
cargo run --example google_search
cargo run --example human_google_search
The framework uses a comprehensive error system:
use surfai::BrowserResult;
match browser.new_page("https://example.com").await {
Ok(page) => {
// Success
}
Err(BrowserError::Navigation(msg)) => {
println!("Navigation error: {}", msg);
}
Err(BrowserError::ElementNotFound(selector)) => {
println!("Element not found: {}", selector);
}
Err(e) => {
println!("Other error: {}", e);
}
}
Fork the repository
Create a feature branch
Make your changes
Add tests for new functionality
Submit a pull request
For issues and questions:
Note: This framework is designed for legitimate automation and testing purposes. Please respect website terms of service and implement appropriate rate limiting and error handling in production use.