Copy-paste-ready code for every major agent framework and language
Simple examples using built-in PHP functions — no Composer or Guzzle needed:
PHP — file_get_contents// Simplest possible fetch — one line
$params = http_build_query([
'url' => 'https://example.com',
'apikey' => 'YOUR_KEY',
'tag' => 'my_script',
]);
$json = file_get_contents("https://www.botanon.com/api/fetch?{$params}");
$data = json_decode($json, true);
if ($data['success']) {
echo $data['body']; // The fetched HTML
echo "\nProxy: " . $data['proxy']['driver'];
} else {
echo "Error: " . $data['error'];
}
PHP — cURL
// cURL for more control (timeouts, POST, headers)
function botanon_fetch(string $url, string $apikey, string $tag = 'php_curl'): array {
$params = http_build_query([
'url' => $url,
'apikey' => $apikey,
'tag' => $tag,
'ua' => 'random',
]);
$ch = curl_init("https://www.botanon.com/api/fetch?{$params}");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_FOLLOWLOCATION => true,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200 || $response === false) {
return ['success' => false, 'error' => "HTTP {$httpCode}"];
}
return json_decode($response, true);
}
// Usage
$result = botanon_fetch('https://example.com', 'YOUR_KEY');
echo $result['body'];
PHP — POST with cURL
$ch = curl_init('https://www.botanon.com/api/fetch');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'url' => 'https://api.example.com/search',
'apikey' => 'YOUR_KEY',
'method' => 'POST',
'post_data' => json_encode(['query' => 'AI agents']),
'post_type' => 'json',
'tag' => 'search',
]),
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
echo $data['body'];
Use BotAnon as a fetch tool in your MCP server or Claude Code skill. Here's a complete PHP function for an MCP server:
PHP — MCP Server Fetch Tool// Example: PHP function an MCP server could use
function botanon_fetch(string $url, string $tag = 'claude_agent'): array {
$client = new \GuzzleHttp\Client();
$response = $client->get('https://www.botanon.com/api/fetch', [
'query' => [
'url' => $url,
'apikey' => getenv('BOTANON_API_KEY'),
'tag' => $tag,
'ua' => 'random',
],
'timeout' => 30,
]);
return json_decode((string)$response->getBody(), true);
}
Python — MCP Server Fetch Tool
import os
import requests
def botanon_fetch(url: str, tag: str = "claude_agent") -> dict:
"""Fetch a URL through BotAnon for anonymous access."""
resp = requests.get("https://www.botanon.com/api/fetch", params={
"url": url,
"apikey": os.environ["BOTANON_API_KEY"],
"tag": tag,
"ua": "random",
}, timeout=30)
resp.raise_for_status()
data = resp.json()
if not data["success"]:
raise Exception(f"BotAnon error: {data.get('error', 'unknown')}")
return data
Autonomous agents that scrape multiple URLs can loop through BotAnon with built-in rate limiting and error handling:
Python — Autonomous Agent Loopimport requests
import time
BOTANON_API = "https://www.botanon.com/api/fetch"
API_KEY = "YOUR_KEY"
def agent_fetch(url, tag="hermes_agent"):
resp = requests.get(BOTANON_API, params={
"url": url,
"apikey": API_KEY,
"tag": tag,
"ua": "random",
})
data = resp.json()
if data["success"]:
return data["body"]
raise Exception(f"Fetch failed: {data.get('error', 'unknown')}")
# Agent workflow example
urls = [
"https://example.com/pricing",
"https://example.com/about",
"https://example.com/contact",
]
for url in urls:
html = agent_fetch(url)
# Process html with your LLM...
print(f"Fetched {url}: {len(html)} bytes")
time.sleep(1) # Be respectful
Modern Node.js with the built-in fetch API — no dependencies needed:
const BOTANON_API = 'https://www.botanon.com/api/fetch';
async function agentFetch(url, tag = 'node_agent') {
const params = new URLSearchParams({
url, apikey: process.env.BOTANON_API_KEY, tag, ua: 'random'
});
const resp = await fetch(`${BOTANON_API}?${params}`);
const data = await resp.json();
if (!data.success) throw new Error(data.error);
return data;
}
// Use in your agent
const result = await agentFetch('https://example.com');
console.log(`HTTP ${result.http_code}, ${result.body_size} bytes via ${result.proxy.driver}`);
Quick command-line examples for testing or shell-based agent workflows:
Bash — Simple GETcurl -s 'https://www.botanon.com/api/fetch?url=https://example.com&apikey=YOUR_KEY&tag=shell' | jq .
Bash — POST with JSON data
curl -s -X POST https://www.botanon.com/api/fetch \
-H 'Content-Type: application/json' \
-d '{"url":"https://api.example.com/search","apikey":"YOUR_KEY","method":"POST","post_data":"{\"q\":\"test\"}","post_type":"json"}' | jq .
Bash — With compression
curl -s --compressed 'https://www.botanon.com/api/fetch?url=https://example.com&apikey=YOUR_KEY&compress=1' | jq .
Bash — Browser rendering (JS-heavy pages)
curl -s 'https://www.botanon.com/api/fetch?url=https://spa-app.com&apikey=YOUR_KEY&browser=1' | jq .body
BotAnon supports form POSTs, JSON POSTs, and custom headers for complex API interactions:
Python — Form POSTresp = requests.post("https://www.botanon.com/api/fetch", json={
"url": "https://example.com/login",
"apikey": "YOUR_KEY",
"method": "POST",
"post_data": "username=agent&password=secret",
"post_type": "form",
"tag": "login_agent",
})
data = resp.json()
print(data["body"])
Python — JSON POST
import json
resp = requests.post("https://www.botanon.com/api/fetch", json={
"url": "https://api.example.com/search",
"apikey": "YOUR_KEY",
"method": "POST",
"post_data": json.dumps({"query": "AI agents", "limit": 10}),
"post_type": "json",
"tag": "search_agent",
})
data = resp.json()
print(data["body"])
PHP — Custom User-Agent & Timeout
$response = $client->get('https://www.botanon.com/api/fetch', [
'query' => [
'url' => 'https://tough-target.com',
'apikey' => 'YOUR_KEY',
'ua' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/125.0.0.0',
'timeout' => 60,
'browser' => 1,
'tag' => 'tough_target',
],
]);
Always check the success field, implement retries with backoff, and use tags for debugging:
import requests
import time
def resilient_fetch(url, tag="my_agent", max_retries=3):
"""Fetch with automatic retries and exponential backoff."""
for attempt in range(max_retries):
try:
resp = requests.get("https://www.botanon.com/api/fetch", params={
"url": url,
"apikey": API_KEY,
"tag": f"{tag}_attempt_{attempt}",
"ua": "random",
"refresh": 1 if attempt > 0 else 0, # Force fresh on retry
}, timeout=30)
data = resp.json()
if data["success"]:
return data
# Non-retryable errors
if data.get("http_code") in [404, 401, 403]:
return data # Don't retry client errors
except requests.RequestException as e:
print(f"Request error: {e}")
if attempt < max_retries - 1:
wait = 2 ** attempt # 1s, 2s, 4s
print(f"Retrying in {wait}s...")
time.sleep(wait)
raise Exception(f"Failed after {max_retries} attempts: {url}")
PHP — Error Handling
function safe_fetch(string $url, string $tag): ?array {
try {
$client = new \GuzzleHttp\Client();
$response = $client->get('https://www.botanon.com/api/fetch', [
'query' => [
'url' => $url,
'apikey' => getenv('BOTANON_API_KEY'),
'tag' => $tag,
],
'timeout' => 30,
]);
$data = json_decode((string)$response->getBody(), true);
if (!$data['success']) {
error_log("BotAnon fetch failed [{$tag}]: " . ($data['error'] ?? 'unknown'));
return null;
}
return $data;
} catch (\Throwable $e) {
error_log("BotAnon exception [{$tag}]: " . $e->getMessage());
return null;
}
}
Search places, look up details, and queue or instant-run crawls.
# Simple search — returns ~20 places
curl "https://www.botanon.com/api/gmaps/search?apikey=KEY&query=bars+Derby"
# Deep search with forced tier
curl "https://www.botanon.com/api/gmaps/search?apikey=KEY&query=pubs+York&depth=5&tier=residential&refresh=1"
# Get details for a known place_id
curl "https://www.botanon.com/api/gmaps/place/0x2fb4e9b346dee95b:0xd5811e26f15ce74d?apikey=KEY"
# Add to crawl queue with high priority
curl -X POST https://www.botanon.com/api/gmaps/crawl \
-H 'Content-Type: application/json' \
-d '{
"apikey": "KEY",
"query": "pest_control in Sevenoaks, Kent, GB",
"mode": "queue",
"priority": 1,
"region": "Kent",
"category": "pest_control"
}'
# Auto-detect location/category from query string
curl -X POST https://www.botanon.com/api/gmaps/crawl \
-H 'Content-Type: application/json' \
-d '{"apikey": "KEY", "query": "plumbers in Bristol, GB"}'
# Get results immediately (10-60 seconds)
curl -X POST https://www.botanon.com/api/gmaps/crawl \
-H 'Content-Type: application/json' \
-d '{
"apikey": "KEY",
"query": "restaurants in Albufeira, PT",
"mode": "instant",
"depth": 3
}'
# Crawl the area around a known place (derives location + category)
curl -X POST https://www.botanon.com/api/gmaps/crawl \
-H 'Content-Type: application/json' \
-d '{
"apikey": "KEY",
"place_id": "ChIJqfzVUcwEdkgR7cvsVYJ8daE"
}'
# Override category — find restaurants near a pub's location
curl -X POST https://www.botanon.com/api/gmaps/crawl \
-H 'Content-Type: application/json' \
-d '{
"apikey": "KEY",
"place_id": "ChIJqfzVUcwEdkgR7cvsVYJ8daE",
"category": "restaurant",
"priority": 2
}'
# → Derives: "restaurant in London, GB"
import requests
# Queue with high priority
resp = requests.post("https://www.botanon.com/api/gmaps/crawl", json={
"apikey": "KEY",
"query": "electricians in Cardiff, GB",
"mode": "queue",
"priority": 1,
"region": "Cardiff",
})
data = resp.json()
print(f"Queued: #{data['queue_id']} at priority {data['priority']}")
# Instant scrape
resp = requests.post("https://www.botanon.com/api/gmaps/crawl", json={
"apikey": "KEY",
"query": "dentists in Oxford, GB",
"mode": "instant",
"depth": 3,
})
data = resp.json()
print(f"Found {data['places_count']} places in {data['duration_seconds']:.1f}s")
// Queue a crawl
$ch = curl_init('https://www.botanon.com/api/gmaps/crawl');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'apikey' => 'KEY',
'query' => 'roofers in Leeds, GB',
'mode' => 'queue',
'priority' => 2,
'region' => 'Leeds',
'category' => 'roofers',
]),
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
echo "Queue ID: {$data['queue_id']}\n";
Search Twitter/X via authenticated cookie-based accounts. Results cached 24h.
curl -X POST https://www.botanon.com/api/twitter-search \
-H 'Content-Type: application/json' \
-d '{
"apikey": "KEY",
"q": "faro airport queue OR delay OR busy -filter:retweets",
"max": 10
}'
import requests
resp = requests.post("https://www.botanon.com/api/twitter-search", json={
"apikey": "KEY",
"q": "faro airport queue OR delay since:2026-05-01",
"max": 10,
})
data = resp.json()
for tweet in data.get("tweets", []):
print(f"@{tweet['author']}: {tweet['text'][:80]}")
# Add account (cookies from Chrome DevTools → x.com)
curl -X POST https://www.botanon.com/api/twitter-search \
-H 'Content-Type: application/json' \
-d '{
"apikey": "KEY",
"action": "add-account",
"username": "myxaccount",
"auth_token": "abc123...",
"ct0": "xyz789..."
}'
# List loaded accounts
curl -X POST https://www.botanon.com/api/twitter-search \
-H 'Content-Type: application/json' \
-d '{"apikey": "KEY", "action": "accounts"}'