# Agent Async Run
Source: https://docs.nimbleway.com/api-reference/agent/agent-async-run
openapi.json post /v1/agents/async
Execute Search Agent Async Endpoint
# Agent Run
Source: https://docs.nimbleway.com/api-reference/agent/agent-run
openapi.json post /v1/agents/run
Execute Search Agent Realtime Endpoint
# Get Agent Details
Source: https://docs.nimbleway.com/api-reference/agent/get-agent-details
openapi.json get /v1/agents/{agent_name}
# List Agents
Source: https://docs.nimbleway.com/api-reference/agent/list-agents
openapi.json get /v1/agents
# Cancel Crawl
Source: https://docs.nimbleway.com/api-reference/crawl/cancel-crawl
openapi.json delete /v1/crawl/{id}
# Crawl by ID
Source: https://docs.nimbleway.com/api-reference/crawl/crawl-by-id
openapi.json get /v1/crawl/{id}
# Create Crawl
Source: https://docs.nimbleway.com/api-reference/crawl/create-crawl
openapi.json post /v1/crawl
# List Crawls
Source: https://docs.nimbleway.com/api-reference/crawl/list-crawls
openapi.json get /v1/crawl
# Extract
Source: https://docs.nimbleway.com/api-reference/extract/extract
openapi.json post /v1/extract
# Extract Async
Source: https://docs.nimbleway.com/api-reference/extract/extract-async
openapi.json post /v1/extract/async
# Introduction
Source: https://docs.nimbleway.com/api-reference/introduction
Get started with Nimble's API
Nimble API provides powerful web scraping and data extraction capabilities through a simple REST API. Extract data from any website, use pre-built templates for popular platforms, search the web, map site structures, and crawl entire websites at scale.
## API Features
Extract clean HTML and structured data from any URL with custom parsing and
browser actions.
Use pre-built agent for popular platforms like Amazon, Google, LinkedIn, and
more.
Search the web and retrieve full content from top results with optional AI
summaries.
Discover all URLs on a website with metadata for planning crawl strategies.
Extract data from entire websites with async crawling across multiple pages.
Retrieve results from async operations (extract, search, map, crawl).
## Base URL
All API requests use the following base URL:
```bash theme={"system"}
https://sdk.nimbleway.com/v1
```
## Authentication
All requests require authentication using a Bearer token in the Authorization header:
```bash theme={"system"}
Authorization: Bearer YOUR_API_KEY
```
Get your API key from the [Nimble Dashboard](https://online.nimbleway.com/account-settings/api-keys).
### Example Request
```bash theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true
}'
```
## Response Codes
Nimble uses standard HTTP status codes to indicate the success or failure of requests.
| Status | Description |
| ------ | -------------------------------------------------------- |
| 200 | Request successful. |
| 400 | Bad request - check your parameters. |
| 401 | Unauthorized - invalid or missing API key. |
| 402 | Payment required - insufficient budget or trial expired. |
| 422 | Validation error - invalid request parameters. |
| 429 | Rate limit exceeded - slow down your requests. |
| 500 | Internal server error - Nimble infrastructure issue. |
## Rate Limits
Nimble enforces rate limits to ensure service stability and fair usage across all users.
### Default Rate Limits
| Driver Type | Rate Limit |
| -------------------- | ------------------ |
| `vx6`, `vx8`, `vx10` | 83 QPS (5,000 QPM) |
**QPS** = Queries Per Second, **QPM** = Queries Per Minute. Rate limits apply
per API key.
### Rate Limit Headers
Responses include headers showing your current rate limit status:
```bash theme={"system"}
X-RateLimit-Limit: 83
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1609459200
```
### Exceeding Rate Limits
When you exceed the rate limit, you'll receive a 429 status code with retry information:
```json theme={"system"}
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Current limit: 83 QPS",
"retry_after": 2
}
}
```
**Need higher limits?** Contact [sales@nimbleway.com](https://login.start-chat.com/modal/601e4da4-50a0-4dc7-8155-bb84f2952c40/27847549-dc04-4144-98a5-d40e568bf6af?magicLinkId=slFQ2j\&UID=65ab324c-ecde-4748-9f52-8e395054774b.1753267174019) for custom rate limits.
## Async Operations
Several endpoints support asynchronous processing for long-running operations:
* `/v1/extract/async` - Async data extraction
* `/v1/agent/async` - Async template extraction
* `/v1/search/async` - Async web search
* `/v1/map/async` - Async site mapping
* `/v1/crawl` - Crawl operations (async only)
### Working with Async Tasks
1. **Start an async operation** - Returns a task ID
2. **Check task status** - Use `/v1/tasks/{id}` to check progress
3. **Retrieve results** - Get results from `/v1/tasks/{id}/results` when complete
```bash theme={"system"}
# Start async extraction
curl -X POST 'https://sdk.nimbleway.com/v1/extract/async' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{"url": "https://example.com"}'
# Returns: {"task_id": "8e8cfde8-345b-42b8-b3e2-0c61eb11e00f"}
# Check task status
curl 'https://sdk.nimbleway.com/v1/tasks/8e8cfde8-345b-42b8-b3e2-0c61eb11e00f' \
--header 'Authorization: Bearer YOUR_API_KEY'
# Get results when complete
curl 'https://sdk.nimbleway.com/v1/tasks/8e8cfde8-345b-42b8-b3e2-0c61eb11e00f/results' \
--header 'Authorization: Bearer YOUR_API_KEY'
```
## Next Steps
Make your first API request in minutes
Understand rate limits and technical specifications
# Map
Source: https://docs.nimbleway.com/api-reference/map/map
openapi.json post /v1/map
# Search
Source: https://docs.nimbleway.com/api-reference/search/search
openapi.json post /v1/search
# Task Result
Source: https://docs.nimbleway.com/api-reference/tasks/task-result
openapi.json get /v1/tasks/{id}/results
Retrieve the status and results of an async task by ID. Works for all async task types (extract, search, map, agent, crawl).
# Task Status
Source: https://docs.nimbleway.com/api-reference/tasks/task-status
openapi.json get /v1/tasks/{id}
Retrieve the status and results of an async task by ID. Works for all async task types (extract, search, map, agent, crawl).
# Changelog
Source: https://docs.nimbleway.com/changelog/release-notes
Stay up to date with the latest Nimble SDK updates and improvements
Track new features, improvements, and updates to the Nimble SDK and Web Tools. We ship updates regularly to enhance performance, add capabilities, and improve your developer experience.
Have feedback or questions about a release? [Reach out to our team](https://portal.usepylon.com/nimble)
### Release Notes for February, 2026
### New Features
#### GET Agents API
New endpoints for discovering and exploring available web search agents. List all available agent templates with `GET /agents` or retrieve detailed information about a specific agent including its input/output schema with `GET /agents/{agent_name}`. \
Perfect for building dynamic agent selections or understanding agent capabilities programmatically. [View Documentation](/nimble-sdk/agentic/agent-gallery)
#### Screenshot Format
New `screenshot` format option for the Extract API. Capture full-page screenshots as base64-encoded PNG images for visual verification, monitoring, and archival. Screenshots automatically enable JavaScript rendering (VX8/VX10 driver). [View Documentation](/nimble-sdk/web-tools/extract/features/formats)
### Documentation
#### Documentation Updates
* **Callbacks & Delivery Guide**: Comprehensive guide covering all async result delivery options - polling, webhooks, and cloud delivery to S3/GCS. Includes setup instructions for bucket permissions. [View Guide](/nimble-sdk/admin/callbacks-and-delivery)
* **Integration Documentation**: New guide covering all available integration and AI connectors to Nimble SDK capabilities. [View Integrations](/integrations)
### New Features
#### Agent Skills API
Advanced web search skills powered by Nimble Search API. Built on the open-source [Agent Skills](https://agentskills.io/) standard for cross-platform agent compatibility, connected to you Claude, Cursor and more.
Features 8 specialized focus modes (general, coding, news, academic, shopping, social, geo, location) with AI-powered answer generation and smart result filtering. [Try Now](/integrations/agent-skills/nimble-web-tools-skill)
### Release Notes for January, 2026
### Documentation
#### Comprehensive Guides
* **Quickstart Pages**: New quickstart guides for all Web Tools with installation steps, basic usage examples, common patterns, and next steps. Get started in under 5 minutes.
* **Usage Documentation**: Detailed usage pages for each Web Tool covering all parameters, response formats, best practices, common use cases, and limitations.
* **API Reference**: Complete API reference with request/response schemas, error codes, rate limits, and authentication methods for all endpoints. [Try Now](/api-reference/introduction)
* **Account Management**: New guide covering API key generation, team member management, permissions, and security best practices. [View Guide](/nimble-sdk/admin/account-management)
* **Integration Documentation**: New guide covering all available integration and AI connectors to Nimble SDK capabilities. [View Integrations](/integrations)
### New Features
#### Extract API
The `/extract` retrieves clean HTML, text, and structured data from any webpage. Supports JavaScript rendering, stealth mode for anti-bot protection, custom parsing with CSS selectors, browser actions, screenshots, and network request capture. [Try Now](/nimble-sdk/web-tools/extract/quickstart)
### New Features
#### Web Search Agents API
The `/agent` are ready-to-use web search agent extractors for popular websites like Amazon, Google, LinkedIn, and hundreds more. No coding or CSS selectors required - just provide the template name, and template inputs such as search term or product ID and get structured data instantly. Agents are maintained 24/7 by Nimble and automatically updated when sites change. [Try Now](/nimble-sdk/agentic/agents)
### New Features
#### Search API
The `/search` perform web searches and retrieve parsed content from top results. Supports fast mode for URL discovery, deep search mode with full content extraction, and AI-powered answer summaries from search results. [Try Now](/nimble-sdk/web-tools/search)
### New Features
#### Map API
The `/map` perform fast URL discovery and site structure mapping. Ideal for discovering all pages on a website, extracting sitemap URLs, and understanding site architecture without deep crawling overhead. Supports subdomain filtering and exact domain matching. [Try Now](/nimble-sdk/web-tools/map)
### New Features
#### Crawl API
The `/crawl` perform deep website crawling for comprehensive data extraction across multiple pages. Features smart navigation, data normalization, and multi-page scraping with automatic traversing handling. [Try Now](/nimble-sdk/web-tools/crawl)
# Build Your First Agent
Source: https://docs.nimbleway.com/guides/build-first-agent-tutorial
Give Claude one prompt and let the Nimble Agents skill handle agent discovery, custom agent generation, and script writing — end to end
## What You'll Build
A Python script that pulls running shoe data from **Amazon**, **Walmart**, and **Nike.com** and outputs a ranked, cross-retailer price comparison — all from a single prompt to your AI coding assistant.
The Nimble Agents skill handles the rest:
* **Finds** pre-built agents for sites already in the gallery (Amazon, Walmart)
* **Generates** a custom agent for any site that isn't (Nike.com)
* **Writes** the full analysis script using the agents it collected
## Prerequisites
Sign up free and grab your API key from Account Settings
Install the Nimble plugin for Claude Code or Cursor
You'll also need Python 3.8+ and the Nimble SDK:
```bash theme={"system"}
pip install nimble_python
```
***
## Step 1: Give Claude the Prompt
Open a new session in Claude Code (or Cursor) and paste this prompt:
```
Build a Python script that runs competitive analysis on running shoes across
Amazon, Walmart, and Nike.com. Use Nimble for all data collection.
For each retailer:
- Search the Nimble agent gallery for an existing agent. Use it if one exists.
- If no agent exists for that site, use the Nimble Agents skill to generate
a custom one, then publish it for reuse.
The script should collect product name, price, rating (if available), and URL
from each source, then print a unified list sorted by price and save the full
results to shoe_analysis.json.
My Nimble API key is set as the NIMBLE_API_KEY environment variable.
```
```
Build a Python script that runs competitive analysis on running shoes across
Amazon, Walmart, and Nike.com. Use Nimble for all data collection.
For each retailer:
- Search the Nimble agent gallery for an existing agent. Use it if one exists.
- If no agent exists for that site, use the Nimble Agents skill to generate
a custom one, then publish it for reuse.
The script should collect product name, price, rating (if available), and URL
from each source, then print a unified list sorted by price and save the full
results to shoe_analysis.json.
My Nimble API key is set as the NIMBLE_API_KEY environment variable.
```
That's it. Claude takes it from here.
***
## What Claude Does Next
Claude works through the task autonomously using the Nimble Agents skill. Here's what happens under the hood:
Claude calls `nimble_agents_list` with the query `"amazon"` and finds `amazon_serp` — a pre-built agent for Amazon search results. It inspects the schema and confirms `keyword` is the required input.
Same flow for Walmart — finds `walmart_search`, confirms it takes a `keyword` param and returns product name, price, and rating.
No public agent exists for `nike.com`. Claude calls `nimble_agents_generate` with a description of what's needed, waits for the agent to be created, runs a test extraction, and publishes it as `nike_running_shoes_plp`.
With all three agents confirmed, Claude writes `shoe_analysis.py` using the Nimble Python SDK and the agent names it just collected.
The script Claude produces will look something like this:
```python theme={"system"}
import json
import os
from nimble_python import Nimble
nimble = Nimble(api_key=os.environ["NIMBLE_API_KEY"])
KEYWORD = "running shoes"
NIKE_URL = "https://www.nike.com/w/mens-running-shoes"
def fetch_amazon():
result = nimble.agent.run(
agent="amazon_serp",
params={"keyword": KEYWORD}
)
products = result.data.parsing.get("parsed", [])
return [
{
"source": "Amazon",
"name": p.get("product_name"),
"price": p.get("price"),
"rating": p.get("average_rating"),
"url": p.get("product_url"),
}
for p in products
if p.get("price")
]
def fetch_walmart():
result = nimble.agent.run(
agent="walmart_search",
params={"keyword": KEYWORD}
)
products = result.data.parsing.get("parsed", [])
return [
{
"source": "Walmart",
"name": p.get("product_name"),
"price": p.get("price"),
"rating": p.get("rating"),
"url": p.get("product_url"),
}
for p in products
if p.get("price")
]
def fetch_nike():
result = nimble.agent.run(
agent="nike_running_shoes_plp",
params={"url": NIKE_URL}
)
products = result.data.parsing.get("parsed", [])
return [
{
"source": "Nike",
"name": p.get("product_name"),
"price": p.get("price"),
"colors": p.get("colors", []),
"url": p.get("url"),
}
for p in products
if p.get("price")
]
def run_analysis():
print(f'Competitive analysis: "{KEYWORD}"\n')
all_products = []
print("Fetching Amazon...")
all_products.extend(fetch_amazon())
print("Fetching Walmart...")
all_products.extend(fetch_walmart())
print("Fetching Nike...")
all_products.extend(fetch_nike())
sorted_products = sorted(all_products, key=lambda x: x["price"])
print(f"\n{'=' * 55}")
print(f" RESULTS — {len(all_products)} products across 3 retailers")
print(f"{'=' * 55}\n")
for i, p in enumerate(sorted_products[:15], 1):
stars = f" ★{p['rating']}" if p.get("rating") else ""
colors = f" ({len(p['colors'])} colors)" if p.get("colors") else ""
print(f"{i:2}. [{p['source']:7}] ${p['price']:<8.2f} {p['name']}{stars}{colors}")
with open("shoe_analysis.json", "w") as f:
json.dump(all_products, f, indent=2)
print(f"\nFull results saved to shoe_analysis.json")
if __name__ == "__main__":
run_analysis()
```
The exact agent names (e.g. `nike_running_shoes_plp`) are chosen by the skill at generation time. Claude will use whatever names were returned and write the script accordingly — you don't need to track them manually.
***
## Step 2: Run the Script
```bash theme={"system"}
python shoe_analysis.py
```
Expected output:
```
Competitive analysis: "running shoes"
Fetching Amazon...
Fetching Walmart...
Fetching Nike...
=======================================================
RESULTS — 62 products across 3 retailers
=======================================================
1. [Walmart ] $19.98 Athletic Works Men's Knit Running Shoe ★4.1
2. [Walmart ] $29.98 Starter Men's Athletic Running Shoe ★4.0
3. [Walmart ] $44.97 Skechers Go Run Consistent ★4.3
4. [Amazon ] $54.99 New Balance Men's 515 V3 Sneaker ★4.5
5. [Walmart ] $54.98 Nike Downshifter 12 ★4.5
6. [Amazon ] $64.99 Adidas Men's Runfalcon 3.0 ★4.6
7. [Amazon ] $69.99 Nike Men's Revolution 7 ★4.6
8. [Nike ] $110.00 Nike Pegasus Trail 5 (3 colors)
9. [Amazon ] $119.95 Brooks Ghost 15 ★4.7
10. [Nike ] $130.00 Nike Pegasus 41 (5 colors)
...
Full results saved to shoe_analysis.json
```
***
## What's Next
Target, Best Buy, and others are already in the gallery — just ask Claude to extend the script
View and manage your generated Nike agent in the Nimble Platform UI
Run all three agents in parallel to cut total runtime by 3×
Browse all available public agents across every vertical
# Nimble Documentation
Source: https://docs.nimbleway.com/home
Explore guides, API references, SDKs, and tutorials for building with Nimble's Web Search Agent Platform. Learn how to extract, structure, and stream real-time web data into your applications, AI systems, and analytics workflows with speed, reliability, and scale.
# Nimble Agents Skill
Source: https://docs.nimbleway.com/integrations/agent-skills/nimble-agent-skill
A guided workflow for finding, generating, and running Nimble agents to get structured data from any website.
The Nimble Agents skill provides a step-by-step workflow for extracting structured data from any website using Nimble's agents.
## Quick Install
Full plugin with skills and MCP tools
Setup guides for all platforms
## How It Works
The skill follows a find-or-generate approach:
1. **Search** — Find an existing agent matching your target website
2. **Inspect** — Review the agent's input/output schema
3. **Run** — Execute the agent and get structured results
4. **Generate** — If no existing agent fits, create a custom one using natural language
5. **Publish** — Save generated agents for future reuse
Results are always presented in clean markdown tables with numbered follow-up options.
## Prerequisites
* **Nimble API Key** — [Sign up](https://online.nimbleway.com/signup) and generate a key from your [Account Settings > API Keys](/nimble-sdk/admin/account-management#api-keys)
* **MCP Server Connection** — The skill uses 5 MCP tools (`nimble_agents_list`, `nimble_agents_get`, `nimble_agents_generate`, `nimble_agents_run`, `nimble_agents_publish`) provided by the Nimble MCP server
## Installation
See the [Plugin Installation](/integrations/agent-skills/plugin-installation) page for all options.
### Vercel Agent Skills CLI
```bash theme={"system"}
npx skills add Nimbleway/agent-skills
```
The agents skill requires the MCP server. After installing via `npx skills`, connect the MCP server manually:
```bash theme={"system"}
claude mcp add --transport http nimble-mcp-server https://mcp.nimbleway.com/mcp \
--header "Authorization: Bearer ${NIMBLE_API_KEY}"
```
## Usage
Invoke the skill using the slash command:
```
/nimble:nimble-agents
```
For example:
```
/nimble:nimble-agents extract product details from this Amazon page: https://www.amazon.com/dp/B0DGHRT7PS
```
The skill activates automatically — it searches for a matching agent, lets you pick one, runs it, and returns structured data.
You can also describe your task in plain language without the slash command. If the plugin is installed, Claude Code will recognize when to use the agents skill based on your request.
Invoke the skill by referencing it in Cursor Agent chat:
```
/nimble-agents use nimble mcp to find amazon agents and run them
```
For example:
```
/nimble-agents extract product details from this Amazon page: https://www.amazon.com/dp/B0DGHRT7PS
```
The skill activates automatically — it searches for a matching agent, lets you pick one, runs it, and returns structured data.
You can also describe your task in plain language without the slash command. If the skills and rules are installed, Cursor will recognize when to use the agents skill based on your request.
## MCP Tools Used
| Tool | Purpose |
| ------------------------ | ----------------------------------------- |
| `nimble_agents_list` | Browse agents by keyword |
| `nimble_agents_get` | Get agent details and input/output schema |
| `nimble_agents_generate` | Create custom agents via natural language |
| `nimble_agents_run` | Execute agents and get structured results |
| `nimble_agents_publish` | Save generated agents for reuse |
## Source Code
Full skill documentation, examples, and references:
View the complete skill source including SKILL.md, examples, and API reference
# Nimble Web Tools Skill
Source: https://docs.nimbleway.com/integrations/agent-skills/nimble-web-tools-skill
Real-time web intelligence tools — search, extract, map, and crawl the live web via the [Nimble CLI](https://www.npmjs.com/package/@nimble-way/nimble-cli). Built on the open-source [Agent Skills](https://agentskills.io) standard for cross-platform agent compatibility.
## Tools Overview
| Tool | Description |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Search** | Accurate, real-time web search — AI Agents search the live web to retrieve precise information. 8 focus modes: general, coding, news, academic, shopping, social, geo, location. |
| **Extract** | Scalable data collection with stealth unblocking — get clean, real-time HTML and structured data from any URL. Supports JS rendering and browser emulation. |
| **Map** | Fast URL discovery and site structure mapping — easily plan extraction workflows. |
| **Crawl** | Extract contents from entire websites in a single request — collect large volumes of web data automatically. |
## Quick Install
```bash theme={"system"}
npx skills add Nimbleway/agent-skills
```
## Prerequisites
### 1. Nimble CLI
Install the Nimble CLI globally:
```bash theme={"system"}
npm i -g @nimble-way/nimble-cli
```
Verify with:
```bash theme={"system"}
nimble --version
```
### 2. Nimble API Key
Get your key at [online.nimbleway.com](https://online.nimbleway.com/).
Set the `NIMBLE_API_KEY` environment variable using your platform's method:
Add to `~/.claude/settings.json`:
```json theme={"system"}
{
"env": {
"NIMBLE_API_KEY": "your-api-key-here"
}
}
```
```bash theme={"system"}
export NIMBLE_API_KEY="your-api-key-here"
```
Or add to your shell profile (`~/.bashrc`, `~/.zshrc`):
```bash theme={"system"}
echo 'export NIMBLE_API_KEY="your-api-key-here"' >> ~/.zshrc
```
* Add skills to `.github/skills/` in your repository
* Configure API key using GitHub Actions secrets in the copilot environment
* Or set as environment variable in your shell
## Quick Start
The nimble-web-tools skill activates automatically when you ask relevant questions:
```
"Search for recent AI developments"
-> nimble search --query "recent AI developments" --deep-search=false
"Extract the content from this URL"
-> nimble extract --url "https://example.com" --parse --format markdown
"Map all the pages on this docs site"
-> nimble map --url "https://docs.example.com" --limit 100
"Crawl the API docs section"
-> nimble crawl run --url "https://docs.example.com/api" --limit 50
```
## Command Examples
### Search
Accurate, real-time web search with 8 focus modes (general, coding, news, academic, shopping, social, geo, location).
```bash theme={"system"}
# Fast search (recommended — always use --deep-search=false)
nimble search --query "React hooks tutorial" --topic coding --deep-search=false
# Search with AI-generated answer summary
nimble search --query "what is WebAssembly" --include-answer --deep-search=false
# News search with time filter
nimble search --query "AI developments" --topic news --time-range week --deep-search=false
# Domain-filtered search
nimble search --query "auth best practices" \
--include-domain github.com \
--include-domain stackoverflow.com \
--deep-search=false
```
Use `--deep-search=false` for fast responses (1-3s). The default deep mode fetches full page content and is 5-10x slower — only needed for archiving or full-text analysis.
### Extract
Get clean, structured data from any URL with stealth unblocking and JS rendering.
```bash theme={"system"}
# Standard extraction (always use --parse --format markdown)
nimble extract --url "https://example.com/article" --parse --format markdown
# Render JavaScript for SPAs and dynamic content
nimble extract --url "https://example.com/app" --render --parse --format markdown
# Extract with geolocation
nimble extract --url "https://example.com" --country US --city "New York" --parse --format markdown
```
### Map
Discover all URLs on a site to plan extraction workflows.
```bash theme={"system"}
# Map URLs on a site
nimble map --url "https://docs.example.com" --limit 100
# Include subdomains
nimble map --url "https://example.com" --domain-filter subdomains
```
### Crawl
Extract content from entire websites asynchronously.
```bash theme={"system"}
# Start a crawl (always set --limit)
nimble crawl run --url "https://docs.example.com" --limit 50
# Crawl with path filtering
nimble crawl run --url "https://example.com" \
--include-path "/docs" \
--include-path "/api" \
--limit 100
# Check crawl status
nimble crawl status --id "crawl-id"
# List all crawls
nimble crawl list
```
For LLM-friendly output, prefer `map` + `extract --parse --format markdown` on individual pages. Crawl returns raw HTML which can be very large.
## About Agent Skills
This skill follows the [Agent Skills](https://agentskills.io) open-source standard, making it compatible with multiple AI agent platforms. Install using the [Skills CLI](https://www.npmjs.com/package/skills) — the standard package manager for the Agent Skills ecosystem.
## Full Command Reference
For the complete list of options, flags, and advanced usage patterns, see the [SKILL.md on GitHub](https://github.com/Nimbleway/agent-skills/blob/main/skills/nimble-web-tools/SKILL.md).
# Plugin Installation
Source: https://docs.nimbleway.com/integrations/agent-skills/plugin-installation
Install the unified Nimble plugin for Claude Code, Cursor, or Vercel Agent Skills CLI.
The Nimble plugin bundles two skills and an MCP server connection into a single package that works across Claude Code, Cursor, and the Vercel Agent Skills CLI.
## What's Included
| Component | Description |
| -------------------------- | --------------------------------------------------------------------------- |
| **nimble-web-tools** skill | Real-time web intelligence — search, extract, map, and crawl via Nimble CLI |
| **nimble-agents** skill | Find, generate, and run agents |
| **MCP server config** | Pre-configured connection to the Nimble MCP server |
## Prerequisites
1. **Nimble CLI** — Install globally:
```bash theme={"system"}
npm i -g @nimble-way/nimble-cli
```
2. **Nimble API Key** — [Sign up](https://online.nimbleway.com/signup) and generate a key from your [Account Settings > API Keys](/nimble-sdk/admin/account-management#api-keys)
3. Set the environment variable:
```bash theme={"system"}
export NIMBLE_API_KEY="your-api-key-here"
```
Or add to `~/.claude/settings.json` (Claude Code):
```json theme={"system"}
{
"env": {
"NIMBLE_API_KEY": "your-api-key-here"
}
}
```
## Install by Platform
### Nimble Marketplace (recommended)
```bash theme={"system"}
claude plugin marketplace add Nimbleway/agent-skills
claude plugin install nimble@nimble-plugin-marketplace
```
This installs both skills and configures the MCP server automatically.
### Local Plugin Directory
Clone the repo and load it as a local plugin:
```bash theme={"system"}
git clone https://github.com/Nimbleway/agent-skills.git
claude --plugin-dir /path/to/agent-skills
```
### Step 1: Add the MCP Server
Click the button below to add the Nimble MCP server to Cursor instantly:
After installing, replace `NIMBLE_API_KEY` in **Cursor Settings > MCP Servers > nimble-mcp-server** with your actual [Nimble API key](https://online.nimbleway.com/account-settings/api-keys).
Add to `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global):
```json theme={"system"}
{
"mcpServers": {
"nimble-mcp-server": {
"url": "https://mcp.nimbleway.com/mcp",
"headers": {
"Authorization": "Bearer NIMBLE_API_KEY"
}
}
}
}
```
Restart Cursor for changes to take effect.
### Step 2: Add Skills and Rules
Install the skills using the Vercel Agent Skills CLI:
```bash theme={"system"}
npx skills add Nimbleway/agent-skills -a cursor
```
This copies both skills (`nimble-web-tools` and `nimble-agents`) and Cursor rules into your project.
Clone the repo and open the `agent-skills` folder in Cursor:
```bash theme={"system"}
git clone https://github.com/Nimbleway/agent-skills.git
```
Cursor auto-discovers:
* `skills/` — both skills
* `rules/` — Cursor rules (auto-loaded)
* `mcp.json` — MCP server connection
```bash theme={"system"}
npx skills add Nimbleway/agent-skills
```
This installs both skills into your project. To verify:
```bash theme={"system"}
npx skills add Nimbleway/agent-skills --list
```
The agents skill requires the MCP server. After installing via `npx skills`, connect the server manually:
```bash theme={"system"}
claude mcp add --transport http nimble-mcp-server https://mcp.nimbleway.com/mcp \
--header "Authorization: Bearer ${NIMBLE_API_KEY}"
```
## Source Code
View the full plugin source, skill definitions, and development scripts
# LangChain
Source: https://docs.nimbleway.com/integrations/langchain
LangChain tools and retrievers for real-time web search and content extraction.
### Overview
The [`langchain-nimble`](https://pypi.org/project/langchain-nimble/) package provides production-grade LangChain integrations for Nimble's Search and Extract APIs, enabling developers to build RAG applications and AI agents that can search, access, and retrieve online information from anywhere on the web.
The package includes **two retrievers** and **two tools** for comprehensive web data access:
**Retrievers:**
* `NimbleSearchRetriever` - Web search with deep mode, LLM answers, and filtering
* `NimbleExtractRetriever` - Direct URL content extraction
**Tools (for AI Agents):**
* `NimbleSearchTool` - Agent-integrated web search
* `NimbleExtractTool` - Agent-integrated content extraction
#### Key Features
* **Fast + Deep mode** - Quick metadata retrieval or comprehensive content extraction
* **Smart filtering** - Domain and date filtering, topic-based routing
* **Multiple parsing formats** - Plain text, markdown (default), or simplified HTML
* **Full async support** - Both sync and async operations
* **Production-ready** - Retry logic, connection pooling, comprehensive error handling
If you'd like to learn more about the underlying Nimble Search APIs, visit the [documentation here](https://docs.nimbleway.com/nimble-sdk/search-apiw).
### Quick Start
#### Installation
```bash theme={"system"}
pip install -U langchain langchain-nimble langchain-openai
```
#### Setup
Get your API credentials from [Nimble's dashboard](https://online.nimbleway.com/account-settings/api-keys) (free trial available) and set as an environment variable:
```bash theme={"system"}
export NIMBLE_API_KEY="your-api-key"
```
#### Build an AI Agent with Web Search
```python theme={"system"}
from langchain.agents import create_agent
from langchain_nimble import NimbleSearchTool, NimbleExtractTool
from langchain_openai import ChatOpenAI
# Initialize tools
search_tool = NimbleSearchTool()
extract_tool = NimbleExtractTool()
# Create agent with multiple tools
agent = create_agent(
model=ChatOpenAI(model="gpt-5"),
tools=[search_tool, extract_tool],
system_prompt=(
"You are a helpful research assistant with access to "
"real-time web information. You can search the web and "
"extract content from specific URLs."
)
)
# Use the agent
response = agent.invoke({
"messages": [(
"user",
"What are the latest developments in AI agents? "
"Summarize key findings."
)]
})
print(response["messages"][-1].content)
```
### RAG with Knowledge Base
Extract specific URLs as your knowledge base and use them for RAG:
```python theme={"system"}
from langchain_nimble import NimbleExtractRetriever
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
# Extract your knowledge base from specific URLs
retriever = NimbleExtractRetriever(
urls=[
"https://python.langchain.com/docs/concepts/retrievers/",
"https://python.langchain.com/docs/concepts/tools/",
"https://python.langchain.com/docs/tutorials/agents/"
],
output_format="markdown"
)
# Build RAG chain
llm = ChatOpenAI(model="gpt-5", temperature=0)
prompt = ChatPromptTemplate.from_template(
"""Answer based only on the provided documentation.
Documentation: {context}
Question: {question}"""
)
chain = (
{"context": retriever | (lambda docs: "\n\n".join(doc.page_content for doc in docs)),
"question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
# Ask questions about your knowledge base
answer = chain.invoke("What are the key differences between retrievers and tools in LangChain?")
print(answer)
```
### Additional Resources
* [GitHub Repository](https://github.com/Nimbleway/langchain-nimble)
* [PyPI Package](https://pypi.org/project/langchain-nimble/)
* [Example Cookbook](https://github.com/Nimbleway/cookbook)
# Available Tools
Source: https://docs.nimbleway.com/integrations/mcp-server/available-tools
## **Web Search & Content Extraction**
### **nimble\_deep\_web\_search**
Perform comprehensive web searches across multiple search engines with Nimble's advanced infrastructure. This tool serves as your general-purpose web retrieval solution, providing real-time access to search results and extracting content from any website found through Google, Bing, and Yandex searches.
**Use Cases**:
* Generic web content retrieval and data collection
* Real-time information gathering from any website
* General-purpose web scraping and research
### **nimble\_extract**
Extract and parse content from a specific URL when you already know the target webpage. This tool automatically identifies the main content of a webpage and returns it in your preferred format.
**Use Cases**:
* Direct URL content extraction (when you have the link)
* Targeted webpage scraping and monitoring
* Specific article or product page parsing
## **Google Maps & Local Business Intelligence**
### **nimble\_google\_maps\_search**
**Description**: Search Google Maps to discover places and businesses with comprehensive location data. Returns structured information about multiple venues matching your search criteria, including ratings, addresses, and unique place identifiers.
**Use Cases**:
* Local business discovery and analysis
* Competitor location mapping
* Market saturation studies
### **nimble\_google\_maps\_place**
Retrieve comprehensive, real-time information about a specific place from Google Maps. This tool provides the most detailed venue data available, including amenities, accessibility features, business attributes, and rich metadata.
**Use Cases**:
* Detailed venue profiling
* Business intelligence gathering
* Location-based app development
### **nimble\_google\_maps\_reviews**
Collect and analyze customer reviews for any Google Maps location. Provides detailed review content, ratings, timestamps, and reviewer information, enabling comprehensive reputation analysis and customer sentiment tracking.
**Use Cases**:
* Reputation monitoring and management
* Customer sentiment analysis
* Competitive benchmarking
## **E-commerce & Marketplace Intelligence**
### **nimble\_targeted\_engines**
**Description**: Discover available pre-trained extraction templates for major e-commerce platforms. This tool lists all supported websites and their extraction capabilities, helping you identify which platforms and data types can be accessed.
**Use Cases**:
* Platform capability discovery
* Integration planning and scope assessment
* Multi-platform strategy development
### **nimble\_targeted\_retrieval**
**Description**: Execute intelligent data extraction using Nimble's pre-trained AI templates for e-commerce sites. Extracts structured product information from search results, product pages, and category listings across major retail platforms.
**Use Cases**:
* Price monitoring and comparison
* Product catalog management
* Competitive intelligence and market research
## **Agents**
Browse, generate, and run pre-built agents for structured data from any website.
### **nimble\_agents\_list**
Browse the catalog of pre-built agents with keyword search and pagination. Use short keyword queries (e.g. "amazon", "linkedin") to find agents matching your extraction goal.
**Use Cases**:
* Discovering existing agents for a target website
* Browsing available extraction capabilities
* Finding the right agent before building a custom one
### **nimble\_agents\_get**
Get full details of a specific agent including its input/output schema. Returns the agent's description, required input parameters, and the structure of the extracted data.
**Use Cases**:
* Inspecting an agent's capabilities before running it
* Understanding required input parameters
* Reviewing output schema to plan data processing
### **nimble\_agents\_generate**
Create a custom agent from a natural-language description. This is a conversational tool — reuse the same `session_id` across calls to handle follow-up questions, poll for completion, and retrieve the generated agent.
**Use Cases**:
* Building custom extractors for websites without existing agents
* Creating tailored data extraction schemas
* Automating agent creation from business requirements
### **nimble\_agents\_run**
Execute an agent against a target URL or parameters and get structured results. Pass the agent name and input parameters matching the agent's input schema.
**Use Cases**:
* Extracting structured data from web pages
* Running bulk extraction across multiple URLs
* Automating recurring data collection tasks
### **nimble\_agents\_publish**
Save a generated agent so it becomes reusable and searchable in future queries. Uses the same `session_id` from the generation flow.
**Use Cases**:
* Persisting custom agents for team-wide reuse
* Building a library of organization-specific extractors
* Sharing generated agents across projects
## **Data Pipelines**
Create, run, and query automated data pipelines for scheduled extraction workflows.
### **nimble\_pipeline\_list**
Get Nimble Effortless Pipeline definitions. Lists all pipelines available in your account with their configuration and status.
**Use Cases**:
* Viewing existing pipeline configurations
* Monitoring pipeline status and schedules
* Auditing active data collection workflows
### **nimble\_pipeline\_templates**
Get Nimble Effortless Pipeline templates. Browse pre-built pipeline templates that can be customized and deployed for common extraction workflows.
**Use Cases**:
* Discovering available pipeline patterns
* Finding starter templates for common use cases
* Evaluating pipeline capabilities before building custom ones
### **nimble\_pipeline\_create**
Create a new pipeline from a template with optional scheduling. Configure extraction targets, output format, and run frequency.
**Use Cases**:
* Setting up automated data collection
* Creating scheduled extraction workflows
* Deploying pipelines from templates with custom parameters
### **nimble\_pipeline\_run**
Execute/run an existing pipeline definition. Triggers an immediate run of a configured pipeline.
**Use Cases**:
* On-demand pipeline execution
* Testing pipeline configurations
* Triggering data refreshes outside the regular schedule
### **nimble\_pipeline\_metadata**
Get table metadata and schema information for a specific pipeline. Returns the structure of the pipeline's output data.
**Use Cases**:
* Understanding pipeline output format
* Planning downstream data processing
* Validating schema before querying
### **nimble\_pipeline\_query**
Execute SQL queries against pipeline data. Query extracted data using standard SQL syntax for filtering, aggregation, and analysis.
**Use Cases**:
* Analyzing extracted data with SQL
* Building reports and dashboards
* Filtering and aggregating pipeline results
### **nimble\_pipeline\_input\_generate**
Generate structured input data for pipelines using PLP (Product Listing Pages) generation. Automatically creates input parameters for pipeline runs.
**Use Cases**:
* Automating pipeline input preparation
* Generating product listing page URLs at scale
* Bootstrapping pipeline runs with generated inputs
## Nimble Cookbook
Explore our open source Nimble Cookbook on GitHub for ready-to-run examples, best practices, and composable recipes that demonstrate real-world data workflows.
The cookbook includes practical implementations for common use cases across retail, finance, marketing, and AI applications.
# Nimble MCP Server
Source: https://docs.nimbleway.com/integrations/mcp-server/mcp-server
An MCP server enabling AI agents to extract structured web data using Nimble Technologies.
Most AI agents are blind. They hallucinate, they guess, they fail. All because they can't see the real world.
[Model Control Protocol (MCP)](https://modelcontextprotocol.io/) is an open standard developed by [Anthropic](https://www.anthropic.com/). It gives AI agents a simple, standardized way to plug into tools, data, and services.
The Nimble MCP Server bridges this gap by providing real-time, structured web data that transforms how agents interact with the digital world. With tools for web search, location data, business intelligence, agents, and data pipelines, it turns chaotic web information into signals your agents can actually use.
MCP routes results through the LLM context window and can consume tokens
quickly. For typical web retrieval, the [Nimble CLI
skill](/integrations/agent-skills/nimble-web-tools-skill) is more
token-efficient.
## Get Started
Skills, rules, and MCP server
View all 19+ tools and categories
## Prerequisites
**Nimble API Key** — You'll need an API key to authenticate with the MCP server. [Sign up](https://online.nimbleway.com/signup) and generate a key from your [Account Settings > API Keys](/nimble-sdk/admin/account-management#api-keys).
## Setup by Platform
### One-Click Install
Click the button below to add the Nimble MCP server to Cursor instantly:
After installing, replace `NIMBLE_API_KEY` in Cursor Settings > MCP Servers > `nimble-mcp-server` with your actual [Nimble API key](https://online.nimbleway.com/account-settings/api-keys).
Add to `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global):
```json theme={"system"}
{
"mcpServers": {
"nimble-mcp-server": {
"url": "https://mcp.nimbleway.com/mcp",
"headers": {
"Authorization": "Bearer NIMBLE_API_KEY"
}
}
}
}
```
Restart Cursor for changes to take effect.
### Plugin Install (recommended)
Installs both guided skills and the MCP server:
```bash theme={"system"}
claude plugin marketplace add Nimbleway/agent-skills
claude plugin install nimble@nimble-plugin-marketplace
```
See [Plugin Installation](/integrations/agent-skills/plugin-installation) for all options.
### MCP-Only
If you only need the MCP tools:
```bash theme={"system"}
export NIMBLE_API_KEY="Bearer your-nimble-api-key"
claude mcp add --transport http nimble-mcp-server https://mcp.nimbleway.com/mcp \
--header "Authorization: ${NIMBLE_API_KEY}"
```
Add this to your `claude_desktop_config.json`:
```json theme={"system"}
{
"mcpServers": {
"nimble-mcp-server": {
"command": "npx",
"args": [
"-y", "mcp-remote@latest", "https://mcp.nimbleway.com/mcp",
"--header", "Authorization:${NIMBLE_API_KEY}"
],
"env": {
"NIMBLE_API_KEY": "Bearer XXX"
}
}
}
}
```
* Replace `Bearer XXX` with your actual Nimble API key.
* **After modifying the config file, you must restart Claude Desktop for changes to take effect.**
* **macOS**: Quit Claude Desktop completely (Cmd+Q) and relaunch.
* **Windows**: Close the window, then open Task Manager (Ctrl+Shift+Esc), end any "Claude" processes, and relaunch.
For detailed setup instructions and troubleshooting, see the [official MCP quickstart guide](https://modelcontextprotocol.io/quickstart/user).
Any MCP-compatible client can connect to the Nimble MCP server using Streamable HTTP transport.
**Server URL:** `https://mcp.nimbleway.com/mcp`
**Prerequisites:** [Node.js and npm](https://nodejs.org/) installed (for the `mcp-remote` bridge)
```json theme={"system"}
{
"mcpServers": {
"nimble-mcp-server": {
"command": "npx",
"args": [
"-y", "mcp-remote@latest", "https://mcp.nimbleway.com/mcp",
"--header", "Authorization:${NIMBLE_API_KEY}"
],
"env": {
"NIMBLE_API_KEY": "Bearer your-nimble-api-key"
}
}
}
}
```
Replace `your-nimble-api-key` with your actual Nimble API key.
### Available Tools
The Nimble MCP Server provides 19+ tools across five categories:
* **Web Search & Content Extraction** — `nimble_extract`, `nimble_deep_web_search`
* **Google Maps & Local Business** — `nimble_google_maps_search`, `nimble_google_maps_place`, `nimble_google_maps_reviews`
* **E-commerce & Marketplace** — `nimble_targeted_engines`, `nimble_targeted_retrieval`
* **Agents** — `nimble_agents_list`, `nimble_agents_get`, `nimble_agents_generate`, `nimble_agents_run`, `nimble_agents_publish`
* **Data Pipelines** — `nimble_pipeline_list`, `nimble_pipeline_templates`, `nimble_pipeline_create`, `nimble_pipeline_run`, `nimble_pipeline_metadata`, `nimble_pipeline_query`, `nimble_pipeline_input_generate`
View detailed documentation for all tools
### Plugin Installation
For a richer experience with guided skills and workflows, install the Nimble plugin for Claude Code, Cursor, or Vercel Agent Skills CLI.
Install the unified Nimble plugin for Claude Code, Cursor, or Agent Skills CLI
We can't wait to see what cool things your AI agents will do with our tools!
Have ideas for making these tools better or need help getting started? \
Drop us a line - we're here to help your agents get the data they need!
# AdsPower
Source: https://docs.nimbleway.com/integrations/proxy/integration-guides/ads-power
Connect Nimble Proxy with AdsPower
AdsPower provides stealthy browsers that allow you to use multiple social or e-commerce accounts on a single computer simultaneously by providing a unique browser fingerprint for each account.
It also includes a browser automation tool that enables you to run multiple accounts simultaneously as if they were being accessed from different physical devices.
## **Follow these steps to integrate Nimble**
* Download and install the [AdsPower software here.](https://share.adspower.net/rf7gskzRbmRSqfn)
* Launch AdsPower and create a new browser profile.
* Click "New profile" to generate a new virtual browsing profile.
* Enter your profile name, then scroll down to the proxy configuration.
* Configure the proxy server with your browser profile. **HTTP is available with the Nimble IP.**
* In the Nimble User Dashboard, navigate to the [Pipelines](https://app.nimbleway.com/pipelines) page and click “add pipeline” to get your pipeline's proxy connection details.
* In your new pipeline, you will find the IP address, port, username, and password.
* Copy the proxy connection details from the Nimble user dashboard to the AdsPower platform.
Configure the proxy using the following information:
* Proxy type: HTTP
* IP address/Host: [ip.nimbleway.com](http://ip.nimbleway.com)
* Port: 7000
* Username: your pipeline username
* Password: your pipeline password
That's all! AdsPower will now use proxies from Nimble IP
# Android
Source: https://docs.nimbleway.com/integrations/proxy/integration-guides/android
Connect Nimble Proxy with Android
Android is by far the most popular mobile OS on the planet, with upwards of 70% market share.
Connecting an Android device to Nimble IP is easy and straightforward, with no 3rd-party apps needed!
## **Follow these steps to integrate Nimble**
* Fill in the Nimble IP proxy info in the setting proxy server window (don't forget to check "enable proxy server").
* In the Nimble User Dashboard, navigate to the [Pipelines](https://app.nimbleway.com/pipelines) page and click “add pipeline” to get your pipeline's proxy connection details.
* In your new pipeline, you will find the IP address, port, username, and password.
* Copy the proxy connection details from the Nimble user dashboard to the VMLogin platform.
1. To get started, open your device's settings, and then Internet/Network settings.
2. Next, click on the network you’re currently connected to in order to view its properties.
3. Click on the pencil at the top right to edit the network’s settings, and then on “Advanced options”.
4. Scroll down until you see “Proxy”. Set your proxy settings to manual. A few new fields will be added, including “Proxy hostname” and “Proxy port” :
* Hostname: [ip.nimbleway.com](http://ip.nimbleway.com)
* Port: 7000
5. At this point, your phone will begin sending your requests through Nimble IP, but you still need to authenticate your device. To do so, open Chrome and browse to any website. You’ll immediately be asked to sign in with a username and password :
* Username: your pipeline username
* Password: your pipeline password
6. Click Sign in, and you’re done!
1. Open your device's settings, and then click on Mobile Networks.
2. Next, click on “Access Point Names”, or on some devices APNs.
3. Click on the currently active APN.
4. Enter in the following details:
* IP address/Host: [ip.nimbleway.com](http://ip.nimbleway.com)
* Port: 7000
* Username: your pipeline username
* Password: your pipeline password
Because Android is used by many manufacturers, the process may be slightly different on your device. Furthermore, different manufacturers will allow different apps to use proxies, so be sure to check that the app you’d like to use supports proxies.
Congratulations! You’ve connected your Android device, and requests will now be routed through Nimble IP.
# FoxyProxy
Source: https://docs.nimbleway.com/integrations/proxy/integration-guides/foxy-proxy
Connect Nimble Proxy with FoxyProxy
FoxyProxy is a simple and free browser extension that lets you easily use Nimble IP on Firefox or Chrome.
While setting up your proxy server connection can be done without an extension, FoxyProxy provides a simple and flexible interface as well as additional options that browsers lack.
## **Follow these steps to integrate Nimble**
Installing FoxyProxy is very straightforward. \
Simply follow the steps on your browser of choice:
* [Chrome download page](https://chrome.google.com/webstore/detail/foxyproxy-standard/gcknhkkoolaabfmlnjonogaaifnjlfnp)
* [Firefox download page](https://addons.mozilla.org/en-US/firefox/addon/foxyproxy-standard/)
* In the Nimble User Dashboard, navigate to the [Pipelines](https://app.nimbleway.com/pipelines) page and click “add pipeline” to get your pipeline's proxy connection details.
* In your new pipeline, you will find the IP address, port, username, and password.
* Copy the proxy connection details from the Nimble user dashboard to the FoxyProxy platform.
1. After downloading, click the extensions button on the upper right of Chrome and pin the extension to the toolbar
2. Next, click the FoxyProxy icon to open the quick activation menu, and select “Options” to modify the proxy settings.
3. On the left navigation menu, go to “Proxies”.
4. On the options menu to the right, select “Add New Proxy”.
5. In the Proxy Settings dialog that opens, enter the following credentials:
* Host: [ip.nimbleway.com](http://ip.nimbleway.com)
* Port: 7000
* Username: your pipeline username
* Password: your pipeline password
* Check the option to “Save Login Credentials” (click ‘OK’ on the message that pops up, explaining how FoxyProxy handles usernames and passwords)
6. Go to the “General” tab and set a name for your Proxy (we used Nimble)
7. There are two ways to enable the proxy:
1. From the FoxyProxy options page, change the proxy mode from “Disable FoxyProxy” to “Use proxy *yourProfile* for all URLs
2. Alternatively, you can use FoxyProxy’s quick menu to activate the proxy from any page. Click on the FoxyProxy icon in the toolbar, and then select your proxy profile
1. After downloading the add-on, Firefox will automatically add a shortcut to the toolbar. Simply click the FoxyProxy icon to open the quick activation menu, and then click “Options” to modify the proxy settings
2. On the left navigation menu, click “Add” to create a new proxy profile
3. In the “Add Proxy” page, set a name for this proxy setup (we used Nimble), then enter the following details:
* Proxy IP address or DNS name: [ip.nimbleway.com](http://ip.nimbleway.com)
* Port: 7000
* Username: your pipeline username
* Password: your pipeline password
4. There are two ways to enable the proxy:
1. From the FoxyProxy options page, change “Turn Off (Use Firefox Settings)” to the title you set for your proxy profile (we used “Nimble”)
2. Alternatively, you can use FoxyProxy’s quick menu to activate the proxy from any page. Click on the FoxyProxy icon in the toolbar, and then select your proxy profile
That's all! VMLogin will now use proxies from Nimble IP
# Incogniton
Source: https://docs.nimbleway.com/integrations/proxy/integration-guides/incogniton
Connect Nimble Proxy with Incogniton
Incogniton is a multi-session browser that helps you manage multiple online accounts from a single interface while maintaining your privacy and security.
Using Incogniton, you can create multiple virtual browser profiles that act as separate users, each with its own unique digital fingerprint. This allows you to access multiple accounts from a single device without compromising your data or leaving a trace.
## **Follow these steps to integrate Nimble**
* Sign up for a free account at [incogniton.com](http://incogniton.com).
* Download and install the Incogniton software [here](https://incogniton.com/?utm_source=proxy\&utm_campaign=nimbleway).
* Navigate to the "Profile Management" option on the left side of the screen.
* Click the "New profile" button in the top right corner.
* From the left navigation, select "Proxy" and choose the "Proxy type" from the options provided (HTTP, SOCK4, or SOCK5). **HTTP is available with the Nimble IP**.
* In the Nimble User Dashboard, navigate to the [Pipelines](https://app.nimbleway.com/pipelines) page and click “add pipeline” to get your pipeline's proxy connection details.
* In your new pipeline, you will find the IP address, port, username, and password.
* Copy the proxy connection details from the Nimble user dashboard to the Incogniton platform.
Configure the proxy using the following information:
* Proxy type: HTTP
* IP address/Host: [ip.nimbleway.com](http://ip.nimbleway.com)
* Port: 7000
* Username: your pipeline username
* Password: your pipeline password
That's all! Your Incogniton browser will now use proxies from Nimble IP.
# iOS
Source: https://docs.nimbleway.com/integrations/proxy/integration-guides/ios
Connect Nimble Proxy with iPhone and iPad
Setting up iOS to use Nimble IP is simple, straightforward, and requires no third-party apps. iOS natively supports proxy configuration for Wi-Fi connections.
By configuring Nimble on your iOS device, all network traffic on that Wi-Fi connection will route through Nimble's residential proxy network.
## **Follow these steps to integrate Nimble**
* Open the **Settings** app on your iPhone or iPad
* Tap **Wi-Fi**
* Tap the **info icon** (ⓘ) next to your connected Wi-Fi network
* Scroll down to the bottom of the network details
* Tap **Configure Proxy**
* Select **Manual**
Enter the following configuration:
* **Server:** ip.nimbleway.com
* **Port:** 7000
* **Authentication:** Toggle ON
* **Username:** your pipeline username
* **Password:** your pipeline password
In the Nimble User Dashboard, navigate to the [Pipelines](https://app.nimbleway.com/pipelines) page to get your credentials.
* Tap **Save** in the top-right corner
* Your device will now route traffic through Nimble's proxy network
The proxy configuration applies only to this specific Wi-Fi network. You'll need to repeat the setup for each Wi-Fi network where you want to use Nimble.
## Configuration options
| Parameter | Value | Description |
| -------------- | ---------------------- | -------------------------------- |
| Server | `ip.nimbleway.com` | Nimble proxy endpoint |
| Port | `7000` | Default proxy port |
| Authentication | ON | Enable credential authentication |
| Username | Your pipeline username | From your Nimble dashboard |
| Password | Your pipeline password | From your Nimble dashboard |
## Verify your connection
To verify the proxy is working:
1. Open **Safari** or another browser
2. Visit [https://api.ipify.org](https://api.ipify.org) to check your IP address
3. The displayed IP should be different from your regular IP, confirming traffic is routed through Nimble
## Disabling the proxy
To disable the Nimble proxy:
1. Go to **Settings** → **Wi-Fi**
2. Tap the **info icon** (ⓘ) next to your Wi-Fi network
3. Tap **Configure Proxy**
4. Select **Off**
5. Tap **Save**
## Important notes
* **Per-network configuration:** Proxy settings are tied to specific Wi-Fi networks. If you connect to a different network, you'll need to configure the proxy again.
* **Cellular data:** This configuration only affects Wi-Fi traffic. Cellular data connections are not routed through the proxy.
* **All traffic:** Once enabled, all device traffic on that Wi-Fi network routes through Nimble, including apps and system services.
That's all! Your iOS device will now route Wi-Fi traffic through Nimble's proxy network.
# Kameleo
Source: https://docs.nimbleway.com/integrations/proxy/integration-guides/kameleo
Connect Nimble Proxy with Kameleo
Kameleo is a technology that allows you to browse the internet anonymously through stealth browsing. It has a range of tools, including a proprietary API and Selenium Stealth WebDriver, that can automate tasks and create multiple accounts while keeping your identity hidden.
The tool is supported by residential and mobile proxy networks, and this guide will show you how to use Nimble's proxy networks with Kameleo.
## **Follow these steps to integrate Nimble**
* Sign up for an account at [Kameleo.io](http://Kameleo.io)
* Download and install the Kameleo software [here](https://kameleo.io/?ref=13784).
* Navigate to the "New Profile" option on the left side of the screen.
* Choose the browser and OS footprint you wish to use.
* In the Nimble User Dashboard, navigate to the [Pipelines](https://app.nimbleway.com/pipelines) page and click “add pipeline” to get your pipeline's proxy connection details.
* In your new pipeline, you will find the IP address, port, username, and password.
* Copy the proxy connection details from the Nimble user dashboard to the Kameleo platform.
Configure the proxy using the following information:
* Proxy type: HTTP
* IP address/Host: [ip.nimbleway.com](http://ip.nimbleway.com)
* Port: 7000
* Username: your pipeline username
* Password: your pipeline password
That's all! Kameleo will now use proxies from Nimble IP
# macOS
Source: https://docs.nimbleway.com/integrations/proxy/integration-guides/macos
Connect Nimble Proxy with macOS System Preferences
macOS natively supports proxy servers like Nimble IP, allowing installed applications to use the proxy connection for their communications over the internet.
By configuring Nimble at the system level, all applications that respect system proxy settings will automatically route their traffic through Nimble's residential proxy network.
## **Follow these steps to integrate Nimble**
* Click the **Apple menu** () in the top-left corner
* Select **System Settings** (or **System Preferences** on older macOS versions)
* Click on **Network** in the sidebar
* Select your active network connection (e.g., **Wi-Fi** or **Ethernet**) from the list
* Click **Details...** (or **Advanced...** on older versions)
* Select the **Proxies** tab
* Enable **Secure Web Proxy (HTTPS)**
* Enter the proxy configuration:
* **Server:** ip.nimbleway.com
* **Port:** 7000
* Check **Proxy server requires password**
* Enter your credentials:
* **Username:** your pipeline username
* **Password:** your pipeline password
* In the Nimble User Dashboard, navigate to the [Pipelines](https://app.nimbleway.com/pipelines) page to get your credentials.
* Click **OK** to close the proxy settings
* Click **Apply** to save your network configuration
Your secure web traffic will now route through Nimble's proxy network.
## Configuration options
| Parameter | Value | Description |
| --------- | ---------------------- | -------------------------- |
| Server | `ip.nimbleway.com` | Nimble proxy endpoint |
| Port | `7000` | Default proxy port |
| Username | Your pipeline username | From your Nimble dashboard |
| Password | Your pipeline password | From your Nimble dashboard |
## Verify your connection
To verify the proxy is working:
1. Open **Safari** or another browser
2. Visit [https://api.ipify.org](https://api.ipify.org) to check your IP address
3. The displayed IP should be different from your regular IP, confirming traffic is routed through Nimble
## Disabling the proxy
To disable the Nimble proxy:
1. Return to **System Settings** → **Network** → **Details** → **Proxies**
2. Uncheck **Secure Web Proxy (HTTPS)**
3. Click **OK** and **Apply**
Some applications may have their own proxy settings that override system preferences. Check individual application settings if traffic isn't routing through the proxy as expected.
That's all! macOS will now route secure web traffic through Nimble's proxy network.
# MuLogin
Source: https://docs.nimbleway.com/integrations/proxy/integration-guides/mulogin
Connect Nimble Proxy with MuLogin
MuLogin is a multi-session browser that helps you manage multiple online accounts from a single interface while maintaining your privacy and security.
Using MuLogin, you can create multiple virtual browser profiles that act as separate users, each with its own unique digital fingerprint. This allows you to access multiple accounts from a single device without compromising your data or leaving a trace.
## **Follow these steps to integrate Nimble**
* Sign up for an account at [mulogin.com](https://www.mulogin.com/)
* Download and install the MuLogin software [here](https://www.mulogin.com/).
* Launch MuLogin and select "Add Browser" from the right-side menu.
* Locate the "Proxy Settings" section and choose "HTTP" as the protocol type.
* In the Nimble User Dashboard, navigate to the [Pipelines](https://app.nimbleway.com/pipelines) page and click "add pipeline" to get your pipeline's proxy connection details.
* In your new pipeline, you will find the IP address, port, username, and password.
* Copy the proxy connection details from the Nimble user dashboard to the MuLogin platform.
Configure the proxy using the following information:
* Proxy type: HTTP
* IP address/Host: [ip.nimbleway.com](http://ip.nimbleway.com)
* Port: 7000
* Username: your pipeline username
* Password: your pipeline password
Click "Check the network" to validate your proxy connection.
That's all! MuLogin will now use proxies from Nimble IP.
# Multilogin
Source: https://docs.nimbleway.com/integrations/proxy/integration-guides/multilogin
Connect Nimble Proxy with Multilogin
Multilogin provides you with browser and device fingerprints, and together with Nimble IP, you can access sites online from multiple destinations with full anonymity.
Using Multilogin's virtual browser profiles with Nimble's residential proxies, you can manage multiple online accounts while maintaining unique digital identities for each profile.
## **Follow these steps to integrate Nimble**
* Sign up for an account at [multilogin.com](https://multilogin.com/)
* Download and install the Multilogin software
* Launch Multilogin and log in to your account
* Click **Create New** to create a new browser profile
* Enter a name for your profile
* Select your preferred operating system and browser type
* Navigate to the **Proxy** settings section
* Click **Edit proxy settings**
* Select **HTTP** as the connection type
* Enter the following proxy details:
* **Address:** ip.nimbleway.com
* **Port:** 7000
* **Username:** your pipeline username
* **Password:** your pipeline password
* In the Nimble User Dashboard, navigate to the [Pipelines](https://app.nimbleway.com/pipelines) page to get your credentials.
Enable **"Timezone, WebRTC and Geolocation fingerprints based on the external IP"** for consistent fingerprinting that matches your proxy location.
* Click **Check proxy** to verify the connection is working
* You should see a success message with your proxy IP
* Click **Create profile** to save your configuration
Your Multilogin profile will now route all traffic through Nimble's proxy network.
## Configuration options
| Parameter | Value | Description |
| --------------- | ---------------------- | -------------------------- |
| Connection type | HTTP | Proxy protocol |
| Address | `ip.nimbleway.com` | Nimble proxy endpoint |
| Port | `7000` | Default proxy port |
| Username | Your pipeline username | From your Nimble dashboard |
| Password | Your pipeline password | From your Nimble dashboard |
## Geo-targeting
You can control geo-targeting in two ways:
### Option 1: Pipeline settings (recommended)
Configure your target country directly in your Nimble pipeline settings. This applies to all connections using that pipeline.
### Option 2: Username string
Append the country code to your username for profile-level control:
```
your-username-country-us # Route through US
your-username-country-gb # Route through UK
your-username-country-de # Route through Germany
```
This is useful when you need different profiles to connect through different countries.
That's all! Multilogin will now use proxies from Nimble IP.
# Proxifier
Source: https://docs.nimbleway.com/integrations/proxy/integration-guides/proxifier
Connect Nimble Proxy with Proxifier
Proxifier is a network gateway that allows applications that do not support working through proxy servers to operate through a SOCKS or HTTPS proxy.
Using Proxifier with Nimble, you can selectively route specific applications through residential IPs without redirecting all your traffic through the proxy network.
## **Follow these steps to integrate Nimble**
* Download and install Proxifier from [proxifier.com](https://www.proxifier.com/)
* Launch Proxifier after installation
This guide uses Windows as an example, but macOS follows the same configuration steps.
* Navigate to **Profile** → **Proxy Servers**
* Click **Add** to create a new proxy server
* Enter the following server details:
* **Address:** ip.nimbleway.com
* **Port:** 7000
* **Protocol:** HTTPS
* Enable the **Authentication** checkbox
* Select **Username and Password**
* Enter your credentials:
* **Username:** your pipeline username
* **Password:** your pipeline password
* In the Nimble User Dashboard, navigate to the [Pipelines](https://app.nimbleway.com/pipelines) page to get your credentials.
* Click **Check** to test the connection
* You should see a success message confirming the proxy is working
* Click **OK** to save your configuration
We recommend you do not set Nimble IP as your default proxy server to avoid routing all traffic through the proxy unnecessarily.
## Adding proxy rules
You can configure which applications use the Nimble proxy:
1. Go to **Profile** → **Proxification Rules**
2. Click **Add** to create a new rule
3. Configure the rule:
* **Name:** Give your rule a descriptive name
* **Applications:** Select specific applications to route through the proxy
* **Target hosts:** Optionally specify domains or ports
* **Action:** Select your Nimble proxy server
This allows you to route only specific applications (like browsers or scraping tools) through Nimble while keeping other traffic direct.
## DNS configuration
For optimal performance, configure DNS resolution through Nimble:
1. Go to **Profile** → **Name Resolution**
2. Select **Resolve hostnames through proxy**
3. Click **OK** to save
This ensures DNS queries are also routed through Nimble's infrastructure.
## Configuration options
| Parameter | Value | Description |
| --------- | ---------------------- | -------------------------- |
| Address | `ip.nimbleway.com` | Nimble proxy endpoint |
| Port | `7000` | Default proxy port |
| Protocol | HTTPS | Secure proxy protocol |
| Username | Your pipeline username | From your Nimble dashboard |
| Password | Your pipeline password | From your Nimble dashboard |
That's all! Proxifier will now route selected applications through Nimble's proxy network.
# Puppeteer
Source: https://docs.nimbleway.com/integrations/proxy/integration-guides/puppeteer
Connect Nimble Proxy with Puppeteer
Puppeteer is a Node.js library that provides a high-level API to control Chrome or Chromium browsers. It's commonly used for web scraping, automated testing, and generating screenshots or PDFs of web pages.
By integrating Nimble's proxy network with Puppeteer, you can route your automated browser requests through residential IPs, enabling access to geo-restricted content and avoiding IP-based blocking.
## Prerequisites
* Node.js installed on your system
* Nimble account with proxy credentials
## **Follow these steps to integrate Nimble**
Install Puppeteer and the proxy-chain package, which handles proxy authentication:
```bash theme={"system"}
npm install puppeteer proxy-chain
```
* In the Nimble User Dashboard, navigate to the [Pipelines](https://app.nimbleway.com/pipelines) page and click "add pipeline" to get your pipeline's proxy connection details.
* In your new pipeline, you will find the IP address, port, username, and password.
* Your proxy URL format will be: `http://username:password@ip.nimbleway.com:7000`
Use the following code to connect Puppeteer through Nimble's proxy:
```javascript theme={"system"}
const puppeteer = require('puppeteer');
const proxyChain = require('proxy-chain');
(async () => {
// Replace with your Nimble pipeline credentials
const proxyUrl = 'http://YOUR_USERNAME:YOUR_PASSWORD@ip.nimbleway.com:7000';
// Anonymize the proxy URL (handles authentication)
const anonymizedProxy = await proxyChain.anonymizeProxy(proxyUrl);
// Launch browser with proxy
const browser = await puppeteer.launch({
args: [
`--proxy-server=${anonymizedProxy}`,
'--no-sandbox',
'--disable-setuid-sandbox'
],
headless: true
});
try {
const page = await browser.newPage();
// Navigate to your target URL
await page.goto('https://example.com');
// Get page content
const content = await page.content();
console.log('Page loaded successfully');
// Take a screenshot (optional)
await page.screenshot({ path: 'screenshot.png' });
} finally {
// Clean up
await browser.close();
await proxyChain.closeAnonymizedProxy(anonymizedProxy, true);
}
})();
```
The `proxy-chain` package is required because Puppeteer doesn't natively support proxy authentication. It creates a local proxy server that handles the authentication for you.
## Configuration options
| Parameter | Value | Description |
| --------- | ---------------------- | -------------------------- |
| Host | `ip.nimbleway.com` | Nimble proxy endpoint |
| Port | `7000` | Default proxy port |
| Username | Your pipeline username | From your Nimble dashboard |
| Password | Your pipeline password | From your Nimble dashboard |
## Geo-targeting example
To route requests through a specific country, append the country code to your username:
```javascript theme={"system"}
// Route through US proxies
const proxyUrl = 'http://YOUR_USERNAME-country-us:YOUR_PASSWORD@ip.nimbleway.com:7000';
// Route through UK proxies
const proxyUrl = 'http://YOUR_USERNAME-country-gb:YOUR_PASSWORD@ip.nimbleway.com:7000';
```
## Verify your connection
You can verify your proxy connection by checking your IP address:
```javascript theme={"system"}
const puppeteer = require('puppeteer');
const proxyChain = require('proxy-chain');
(async () => {
const proxyUrl = 'http://YOUR_USERNAME:YOUR_PASSWORD@ip.nimbleway.com:7000';
const anonymizedProxy = await proxyChain.anonymizeProxy(proxyUrl);
const browser = await puppeteer.launch({
args: [`--proxy-server=${anonymizedProxy}`],
headless: true
});
const page = await browser.newPage();
await page.goto('https://api.ipify.org?format=json');
const ipInfo = await page.evaluate(() => document.body.textContent);
console.log('Your proxy IP:', ipInfo);
await browser.close();
await proxyChain.closeAnonymizedProxy(anonymizedProxy, true);
})();
```
That's all! Puppeteer will now route all requests through Nimble's proxy network.
# Scrapy
Source: https://docs.nimbleway.com/integrations/proxy/integration-guides/scrapy
Connect Nimble Proxy with Scrapy
Scrapy is a popular open-source web crawling and scraping framework for Python. It's used to crawl websites and extract structured data from their pages, making it ideal for data mining, monitoring, and automated testing.
By integrating Nimble with Scrapy, you can route your crawling requests through residential IPs, enabling access to geo-restricted content and avoiding IP-based blocking at scale.
## Prerequisites
* Python 3.8+ installed on your system
* Nimble account with API credentials
## **Follow these steps to integrate Nimble**
Install the official Nimble middleware for Scrapy:
```bash theme={"system"}
pip install scrapy-nimble
```
* Log in to your [Nimble Dashboard](https://app.nimbleway.com)
* Navigate to Account Settings to find your API credentials
* You'll need your username and password for the configuration
Update your project's `settings.py` file to enable the Nimble middleware:
```python theme={"system"}
# Enable Nimble integration
NIMBLE_ENABLED = True
# Your Nimble credentials
NIMBLE_USERNAME = "your-username"
NIMBLE_PASSWORD = "your-password"
# Register the Nimble middleware
DOWNLOADER_MIDDLEWARES = {
"scrapy_nimble.middlewares.NimbleWebApiMiddleware": 570,
}
```
Ensure the Nimble middleware priority (570) is set to run before the default `HttpCompressionMiddleware` (590).
## Using Nimble in your spiders
Once configured, you can use Nimble features in your spider requests via the `meta` parameter:
```python theme={"system"}
import scrapy
class MySpider(scrapy.Spider):
name = "my_spider"
def start_requests(self):
yield scrapy.Request(
url="https://example.com",
callback=self.parse,
meta={
"nimble_render": True, # Enable JavaScript rendering
"nimble_country": "US", # Geo-target to US
"nimble_locale": "en", # Set locale
}
)
def parse(self, response):
# Your parsing logic here
title = response.css("title::text").get()
yield {"title": title}
```
## Available request options
| Meta Parameter | Type | Description |
| ---------------- | ------- | ------------------------------------------------------------------ |
| `nimble_render` | boolean | Enable JavaScript rendering |
| `nimble_country` | string | Two-letter country code for geo-targeting (e.g., "US", "DE", "GB") |
| `nimble_locale` | string | Locale setting for the request |
## Example spider with geo-targeting
```python theme={"system"}
import scrapy
class GeoSpider(scrapy.Spider):
name = "geo_spider"
countries = ["US", "GB", "DE", "FR"]
def start_requests(self):
for country in self.countries:
yield scrapy.Request(
url="https://example.com",
callback=self.parse,
meta={
"nimble_country": country,
"nimble_render": True,
},
cb_kwargs={"country": country}
)
def parse(self, response, country):
yield {
"country": country,
"title": response.css("title::text").get(),
"content_length": len(response.body),
}
```
## Development setup
For local development, we recommend using a virtual environment:
```bash theme={"system"}
# Create and activate virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install scrapy scrapy-nimble
# Create a new Scrapy project
scrapy startproject myproject
```
That's all! Scrapy will now route all requests through Nimble's infrastructure.
# Selenium
Source: https://docs.nimbleway.com/integrations/proxy/integration-guides/selenium
Connect Nimble Proxy with Selenium
Selenium is a powerful browser automation framework used for web testing, scraping, and automating repetitive browser tasks. It supports multiple programming languages and browsers.
By integrating Nimble's proxy network with Selenium, you can route your automated browser requests through residential IPs, enabling access to geo-restricted content and avoiding IP-based blocking.
## Prerequisites
* Node.js installed on your system
* Nimble account with proxy credentials
## **Follow these steps to integrate Nimble**
Install Selenium WebDriver and the proxy-chain package:
```bash theme={"system"}
npm install selenium-webdriver proxy-chain
```
* In the Nimble User Dashboard, navigate to the [Pipelines](https://app.nimbleway.com/pipelines) page and click "add pipeline" to get your pipeline's proxy connection details.
* In your new pipeline, you will find the IP address, port, username, and password.
* Your proxy URL format will be: `http://username:password@ip.nimbleway.com:7000`
Use the following code to connect Selenium through Nimble's proxy:
```javascript theme={"system"}
const { Builder } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const proxyChain = require('proxy-chain');
(async () => {
// Replace with your Nimble pipeline credentials
const proxyUrl = 'http://YOUR_USERNAME:YOUR_PASSWORD@ip.nimbleway.com:7000';
// Anonymize the proxy URL (handles authentication)
const anonymizedProxy = await proxyChain.anonymizeProxy(proxyUrl);
// Configure Chrome options with proxy
const options = new chrome.Options();
options.addArguments(`--proxy-server=${anonymizedProxy}`);
options.addArguments('--no-sandbox');
options.addArguments('--disable-setuid-sandbox');
// Build the WebDriver
const driver = await new Builder()
.forBrowser('chrome')
.setChromeOptions(options)
.build();
try {
// Navigate to your target URL
await driver.get('https://example.com');
// Get page title
const title = await driver.getTitle();
console.log('Page title:', title);
// Your automation logic here...
} finally {
// Clean up
await driver.quit();
await proxyChain.closeAnonymizedProxy(anonymizedProxy, true);
}
})();
```
The `proxy-chain` package is required because Selenium doesn't natively support proxy authentication with Chrome. It creates a local proxy server that handles the authentication for you.
## Configuration options
| Parameter | Value | Description |
| --------- | ---------------------- | -------------------------- |
| Host | `ip.nimbleway.com` | Nimble proxy endpoint |
| Port | `7000` | Default proxy port |
| Username | Your pipeline username | From your Nimble dashboard |
| Password | Your pipeline password | From your Nimble dashboard |
## Geo-targeting example
To route requests through a specific country, append the country code to your username:
```javascript theme={"system"}
// Route through US proxies
const proxyUrl = 'http://YOUR_USERNAME-country-us:YOUR_PASSWORD@ip.nimbleway.com:7000';
// Route through Germany proxies
const proxyUrl = 'http://YOUR_USERNAME-country-de:YOUR_PASSWORD@ip.nimbleway.com:7000';
```
## Verify your connection
You can verify your proxy connection by checking your IP address:
```javascript theme={"system"}
const { Builder } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const proxyChain = require('proxy-chain');
(async () => {
const proxyUrl = 'http://YOUR_USERNAME:YOUR_PASSWORD@ip.nimbleway.com:7000';
const anonymizedProxy = await proxyChain.anonymizeProxy(proxyUrl);
const options = new chrome.Options();
options.addArguments(`--proxy-server=${anonymizedProxy}`);
const driver = await new Builder()
.forBrowser('chrome')
.setChromeOptions(options)
.build();
await driver.get('https://api.ipify.org');
const ip = await driver.findElement({ css: 'body' }).getText();
console.log('Your proxy IP:', ip);
await driver.quit();
await proxyChain.closeAnonymizedProxy(anonymizedProxy, true);
})();
```
That's all! Selenium will now route all requests through Nimble's proxy network.
# SwitchyOmega
Source: https://docs.nimbleway.com/integrations/proxy/integration-guides/switchyomega
Connect Nimble Proxy with SwitchyOmega browser extension
SwitchyOmega is a free browser extension that lets you manage and switch between multiple proxies quickly and easily. It supports both Chrome and Firefox with an intuitive interface.
Using SwitchyOmega with Nimble, you can easily toggle proxy connections on and off, and even set up automatic rules to route specific websites through different proxies.
## **Follow these steps to integrate Nimble**
Install the extension for your browser:
* **Chrome:** [Chrome Web Store](https://chrome.google.com/webstore/detail/proxy-switchyomega/padekgcemlokbadohgkifijomclgjgif)
* **Firefox:** [Firefox Add-ons](https://addons.mozilla.org/en-US/firefox/addon/switchyomega/)
After installation, pin the extension to your browser toolbar for easy access.
* Click the SwitchyOmega icon in your browser toolbar
* Select **Options** to open the settings interface
* In the left sidebar, click on **proxy** under Profiles
* Enter the following connection details:
* **Protocol:** HTTPS
* **Server:** ip.nimbleway.com
* **Port:** 7000
* Enter your credentials:
* **Username:** your pipeline username
* **Password:** your pipeline password
In the Nimble User Dashboard, navigate to the [Pipelines](https://app.nimbleway.com/pipelines) page to get your credentials.
* Click **Apply changes** to save your proxy settings
* Click the SwitchyOmega icon in your toolbar
* Select your **proxy** profile to activate the connection
Your browser traffic will now route through Nimble's proxy network.
## Configuration options
| Parameter | Value | Description |
| --------- | ---------------------- | -------------------------- |
| Protocol | HTTPS | Secure proxy protocol |
| Server | `ip.nimbleway.com` | Nimble proxy endpoint |
| Port | `7000` | Default proxy port |
| Username | Your pipeline username | From your Nimble dashboard |
| Password | Your pipeline password | From your Nimble dashboard |
## Auto-switch rules
SwitchyOmega allows you to automatically route specific websites through different proxies:
Create separate proxy profiles for different use cases (e.g., different geo-locations or pipelines):
* Click **New profile** in the left sidebar
* Select **Proxy Profile**
* Configure each profile with different Nimble pipeline credentials
* Click on **auto switch** in the left sidebar
* Add rules to route specific domains through specific profiles:
* **Condition type:** Host wildcard
* **Condition:** `*.example.com`
* **Profile:** Select which proxy profile to use
* Click **Apply changes**
* Click the SwitchyOmega icon in your toolbar
* Select **auto switch** to enable automatic profile switching
Now specific websites will automatically route through their assigned proxy profiles.
## Quick switching
Once configured, you can quickly switch between:
* **Direct** - No proxy (direct connection)
* **System Proxy** - Use system-level proxy settings
* **proxy** - Your Nimble proxy profile
* **auto switch** - Automatic rule-based switching
Just click the SwitchyOmega icon and select the desired mode.
That's all! SwitchyOmega will now manage your Nimble proxy connections.
# VMLogin
Source: https://docs.nimbleway.com/integrations/proxy/integration-guides/vm-login
Connect Nimble Proxy with VMLogin
With VMLogin's virtual browsing profiles, you can use physical devices to access and manage multiple online accounts while also benefiting from features like anti-association and fingerprint protection.
These virtual profiles help you protect your online identity and enhance the security of your online accounts.
## **Follow these steps to integrate Nimble**
* Sign up for an account at [VMLogin](https://www.vmlogin.us/?ref=nimble)
* Download and install the VMLogin software [here.](https://www.vmlogin.us/?ref=nimble)
* Launch VMLogin and create a new browser profile.
* Click "Get random profile" to generate a new virtual browsing profile.
* Customize your profile by selecting the settings that best suit you, including the operating system, screen resolution, language, WebGL vendor, time zone, and media device fingerprint.
* Fill in the Nimble IP proxy info in the setting proxy server window (don't forget to check "enable proxy server").
* In the Nimble User Dashboard, navigate to the [Pipelines](https://app.nimbleway.com/pipelines) page and click “add pipeline” to get your pipeline's proxy connection details.
* In your new pipeline, you will find the IP address, port, username, and password.
* Copy the proxy connection details from the Nimble user dashboard to the VMLogin platform.
Configure the proxy using the following information:
* Proxy type: HTTP
* IP address/Host: [ip.nimbleway.com](http://ip.nimbleway.com)
* Port: 7000
* Username: your pipeline username
* Password: your pipeline password
That's all! VMLogin will now use proxies from Nimble IP
# Windows
Source: https://docs.nimbleway.com/integrations/proxy/integration-guides/windows
Connect Nimble Proxy with Windows System Settings
Windows 10 and later natively support proxy servers like Nimble IP. The operating system manages server and port settings, while each application handles its own authentication credentials.
By configuring Nimble at the system level, applications that respect system proxy settings will route their traffic through Nimble's residential proxy network.
## **Follow these steps to integrate Nimble**
* Press the **Windows key** and search for "proxy settings"
* Or navigate to **Settings** → **Network & Internet** → **Proxy**
* Scroll down to **Manual proxy setup**
* Click **Set up** (or toggle **Use a proxy server** to ON on older Windows versions)
* Enter the proxy configuration:
* **Proxy IP address:** ip.nimbleway.com
* **Port:** 7000
* Click **Save**
Windows 10+ requires applications to manage proxy authentication individually. When you access a website through your browser, you'll receive a prompt requesting your Nimble credentials:
* **Username:** your pipeline username
* **Password:** your pipeline password
In the Nimble User Dashboard, navigate to the [Pipelines](https://app.nimbleway.com/pipelines) page to get your credentials.
Most browsers will remember your credentials after the first entry, so you won't need to re-enter them for each request.
## Configuration options
| Parameter | Value | Description |
| ---------------- | ---------------------- | -------------------------- |
| Proxy IP address | `ip.nimbleway.com` | Nimble proxy endpoint |
| Port | `7000` | Default proxy port |
| Username | Your pipeline username | From your Nimble dashboard |
| Password | Your pipeline password | From your Nimble dashboard |
## Alternative: IP allowlisting
Instead of using username/password authentication, you can allowlist your IP address:
1. Log in to your [Nimble Dashboard](https://app.nimbleway.com)
2. Navigate to your Pipeline settings
3. Add your public IP address to the allowlist
4. Connect to the proxy without credentials
This is useful for automated systems or when you prefer not to enter credentials.
## Geo-targeting
To route requests through a specific country, modify your username:
```
your-username-country-us # Route through US
your-username-country-gb # Route through UK
your-username-country-de # Route through Germany
```
## Disabling the proxy
To disable the Nimble proxy:
1. Return to **Settings** → **Network & Internet** → **Proxy**
2. Toggle **Use a proxy server** to OFF
3. Or click **Set up** and disable the proxy
That's all! Windows will now route web traffic through Nimble's proxy network.
# Overview
Source: https://docs.nimbleway.com/integrations/proxy/overview
Step-by-step guides for integrating Nimble IP with popular third-party software
Nimble IP is optimized for compatibility with third-party apps. To help you get started, we've prepared step-by-step guides for integrating Nimble IP with popular third-party software.
***
## Anti-Detect Browsers
Manage multiple accounts with unique browser fingerprints while routing traffic through Nimble's residential proxies.
Virtual browser profiles with fingerprint protection
Multi-session browser for account management
Browser fingerprints with full anonymity
Stealth browsers for multiple accounts
Anonymous stealth browsing technology
Multi-session browser with unique fingerprints
***
## Browser Extensions and Desktop Apps
Quickly switch between proxies directly from your browser or Desktop.
Firefox and Chrome proxy management extension
Manage and switch between multiple proxies
Network gateway for any application
***
## Automation Tools
Integrate Nimble proxies into your web scraping and automation workflows.
Node.js browser automation library
Browser automation framework
Python web crawling framework
***
## Operating Systems
Configure system-level proxy settings for your device.
Windows 10+ system proxy configuration
macOS system preferences proxy setup
iPhone and iPad Wi-Fi proxy configuration
Android device proxy setup
***
## Quick Reference
All integrations use the same core proxy settings:
| Parameter | Value |
| ------------ | ---------------------- |
| **Host** | `ip.nimbleway.com` |
| **Port** | `7000` |
| **Protocol** | HTTP / HTTPS |
| **Username** | Your pipeline username |
| **Password** | Your pipeline password |
Get your proxy credentials from the [Pipelines](https://app.nimbleway.com/pipelines) page in your Nimble dashboard.
# Account Management
Source: https://docs.nimbleway.com/nimble-sdk/admin/account-management
Manage API keys and collaborate with your team
Manage your Nimble account settings, generate API keys, and collaborate with team members all from one centralized dashboard.
## Accessing Account Settings
Navigate to your account settings at [online.nimbleway.com](https://online.nimbleway.com):
1. Log in with your username and password
2. Click on your profile or settings icon
3. Select **Account Settings** from the menu
***
## API Keys
API keys are used to authenticate your requests to the Nimble API. Each key is unique and should be kept secure.
### Generate Your First API Key
In Account Settings, click on the **API Keys** tab
Click the **Create New API Key** button
Give your API key a descriptive name
**Important**: Your API key will only be displayed once. Make sure to copy it immediately and store it securely.
Click **Copy** to save your API key to clipboard
### Managing API Keys
Once created, you can view and manage all your API keys from the API Keys dashboard.
#### API Key Information
Each API key displays the following information:
| Column | Description |
| -------------- | --------------------------------------------------- |
| **Name** | The descriptive name you gave to the key |
| **Created** | Date and time when the key was created |
| **Created By** | The team member who created the key |
| **Last Used** | Most recent date the key was used in an API request |
| **Actions** | Delete or manage the key |
### Delete an API Key
Deleting an API key is permanent and cannot be undone. Any applications using this key will immediately lose access.
To delete an API key:
1. Locate the key you want to delete in the list
2. Click the **Delete** button or trash icon
3. Confirm the deletion in the popup dialog
### Best Practices
Name keys based on their purpose or environment
Create new keys periodically and delete old ones to maintain security
Use separate API keys for different services to track usage and limit exposure
Keep API keys confidential and never commit them to version control
Monitor the "Last Used" column to identify and remove unused API keys
***
## Team Members
Collaborate with your team by inviting members to your Nimble account. Control access levels and manage permissions all in one place.
### Invite Team Members
In Account Settings, click on the **Team Members** tab
Click the **Invite Team Member** button
Type the email address of the person you want to invite
Click **Send Invite** - they'll receive an email with instructions to join
### Managing Team Members
View and manage all team members from the Team Members dashboard.
#### Team Member Information
| Column | Description |
| ----------- | -------------------------------------- |
| **Name** | Team member's full name |
| **Email** | Associated email address |
| **Role** | Permission level (Member or Admin) |
| **Status** | Active, Pending, or Invited |
| **Joined** | Date when they accepted the invitation |
| **Actions** | Change role or remove member |
### Change Member Role
Promote members to admins or revoke admin privileges:
1. Locate the team member in the list
2. Click the **Role** dropdown
3. Select **Admin** or **Member**
4. Changes take effect immediately
Admins have full access to account settings, billing, API keys, and team management
### Remove Team Members
To remove a team member from your account:
1. Find the member in the team list
2. Click the **Remove** button or trash icon
3. Confirm the removal
Removed members will immediately lose access to your account and all its resources
### Permission Levels
**Members can:**
* Use existing API keys
* View usage statistics
* Access documentation
* Make API requests
**Members cannot:**
* Create or delete API keys
* Invite or remove team members
* Access billing information
* Change account settings
**Admins can:**
* Everything Members can do
* Create and delete API keys
* Invite and remove team members
* Promote/demote member roles
* Access billing and payment information
* Modify account settings
**Full account control with no restrictions**
### Team Collaboration Tips
Create unique API keys for each team member to track individual usage and maintain accountability
Only promote trusted team members to admin roles to maintain account security
Encourage team members to use clear names when creating API keys
Periodically review team members and API keys to remove unused accounts
***
## Security Best Practices
* Never commit API keys to version control
* Use environment variables to store keys
* Rotate keys regularly (every 90 days recommended)
* Delete keys immediately if compromised
* Use separate keys for development and production
* Grant minimum necessary permissions
* Remove access for departing team members immediately
* Use admin roles sparingly
* Review team member list regularly
* Monitor API key usage patterns
* Check "Last Used" dates on API keys
* Review team member activity
* Set up alerts for unusual usage
* Track API consumption by key
* Audit changes to account settings
***
## Need Help?
Learn how to use your API keys with our quickstart guide
Contact our support team for account assistance
Test & Explore the API effortleslly, no code is needed
# Blogs
Source: https://docs.nimbleway.com/nimble-sdk/admin/blogs
# Callbacks & Delivery
Source: https://docs.nimbleway.com/nimble-sdk/admin/callbacks-and-delivery
Configure how you receive results from async operations
When using async operations like `/extract/async`, `/agent/async`, or `/crawl`, you have three flexible options for receiving your results. Choose the method that best fits your infrastructure and workflow.
Pull results on-demand using task IDs
Receive push notifications when tasks complete
Automatic delivery to your S3 or GCS bucket
***
## Option 1: Polling (Pull)
The simplest approach - submit your async request, receive a task ID, and poll for results when ready.
Send a request to the async endpoint. You'll receive a task or crawl ID to track your request.
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
response = nimble.extract_async(
url="https://www.nimbleway.com",
render=True,
formats=["html", "markdown"]
)
task_id = response.task_id
print(f"Task submitted: {task_id}")
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const response = await nimble.extractAsync({
url: "https://www.nimbleway.com",
render: true,
formats: ["html", "markdown"]
});
const taskId = response.task_id;
console.log(`Task submitted: ${taskId}`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract/async' \
--header 'Authorization: Bearer YOUR-API-KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.nimbleway.com",
"render": true,
"formats": ["html", "markdown"]
}'
```
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
response = nimble.agent.run_async(
agent="amazon_pdp",
params={"asin": "B0DLKFK6LR"}
)
task_id = response.task_id
print(f"Task submitted: {task_id}")
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const response = await nimble.agent.runAsync({
agent: "amazon_pdp",
params: { asin: "B0DLKFK6LR" }
});
const taskId = response.task_id;
console.log(`Task submitted: ${taskId}`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/agent/async' \
--header 'Authorization: Bearer YOUR-API-KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"agent": "amazon_pdp",
"params": { "asin": "B0DLKFK6LR" }
}'
```
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.crawl.run(
url="https://www.nimbleway.com",
limit=50
)
crawl_id = result.crawl_id
print(f"Crawl started: {crawl_id}")
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.crawl.run({
url: "https://www.nimbleway.com",
limit: 50
});
const crawlId = result.crawl_id;
console.log(`Crawl started: ${crawlId}`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/crawl' \
--header 'Authorization: Bearer YOUR-API-KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.nimbleway.com",
"limit": 50
}'
```
Poll the status endpoint to monitor progress.
```python Python theme={"system"}
import time
while True:
my_task = nimble.tasks.get(task_id)
print(f"Status: {my_task.task.state}")
if my_task.state == "success":
break
elif my_task.state == "failed":
print(f"Task failed: {status.error}")
break
time.sleep(15)
```
```javascript Node theme={"system"}
while (true) {
const myTask = await nimble.tasks.get(taskId);
console.log(`Status: ${myTask.task.state}`);
if (myTask.state === "success") break;
if (myTask.state === "failed") {
console.log(`Task failed: ${status.error}`);
break;
}
await new Promise(resolve => setTimeout(resolve, 15000));
}
```
```bash cURL theme={"system"}
curl 'https://sdk.nimbleway.com/v1/tasks/{task_id}' \
--header 'Authorization: Bearer YOUR-API-KEY'
# Response: { "task": { "id": "...", "state": "completed", ... } }
```
Crawl has its own status endpoint that shows overall progress and individual page tasks.
```python Python theme={"system"}
import time
while True:
my_crawl = nimble.crawl.status(crawl_id)
print(f"Status: {my_crawl.status}")
if status.state == "succeeded":
break
elif status.state == "failed":
print(f"Task failed: {status.error}")
break
time.sleep(2)
```
```javascript Node theme={"system"}
while (true) {
const myCrawl = await nimble.crawl.status(crawlId);
console.log(`Status: ${myCrawl.status}`);
if (status.state === "succeeded") break;
if (status.state === "failed") {
console.log(`Task failed: ${status.error}`);
break;
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
```
```bash cURL theme={"system"}
curl 'https://sdk.nimbleway.com/v1/crawl/{crawl_id}' \
--header 'Authorization: Bearer YOUR-API-KEY'
# Response: { "crawl": { "status": "running", "completed": 10, "total": 50, "tasks": [...] } }
```
Once complete, fetch the full results.
```python Python theme={"system"}
results = nimble.tasks.results(task_id)
print(f"HTML length: {len(results.data.html)}")
print(f"Markdown length: {len(results.data.markdown)}")
```
```javascript Node theme={"system"}
const results = await nimble.tasks.results(taskId);
console.log(`HTML length: ${results.data.html.length}`);
console.log(`Markdown length: ${results.data.markdown.length}`);
```
```bash cURL theme={"system"}
curl 'https://sdk.nimbleway.com/v1/tasks/{task_id}/results' \
--header 'Authorization: Bearer YOUR-API-KEY'
```
```python Python theme={"system"}
results = nimble.tasks.results(task_id)
parsed = results.data.parsing["parsed"]
print(f"Product: {parsed['product_title']}")
print(f"Price: ${parsed['web_price']}")
```
```javascript Node theme={"system"}
const results = await nimble.tasks.results(taskId);
const parsed = results.data.parsing.parsed;
console.log(`Product: ${parsed.product_title}`);
console.log(`Price: $${parsed.web_price}`);
```
```bash cURL theme={"system"}
curl 'https://sdk.nimbleway.com/v1/tasks/{task_id}/results' \
--header 'Authorization: Bearer YOUR-API-KEY'
```
Fetch results for each completed task in the crawl.
```python Python theme={"system"}
# my_crawl["tasks"] from step #2 contains list of task IDs from status response
for task in my_crawl["tasks"]:
if task.state == "success":
task_result = nimble.tasks.get(task_id)
print(f"URL: {task_result['url']}")
print(f"HTML length: {len(task_result['data'].get('html', ''))}")
```
```javascript Node theme={"system"}
// myCrawl.tasks from step #2 contains list of task IDs from status response
for (const task of myCrawl.tasks) {
if (task.status === "completed") {
const taskResponse = await nimble.tasks.get(taskId);
console.log(`URL: ${taskResult.url}`);
console.log(`HTML length: ${taskResult.data?.html?.length || 0}`);
}
}
```
```bash cURL theme={"system"}
# Get results for each task_id from the crawl status response
curl 'https://sdk.nimbleway.com/v1/tasks/{task_id}/results' \
--header 'Authorization: Bearer YOUR-API-KEY'
```
```json theme={"system"}
{
"url": "https://www.nimbleway.com/blog/post",
"task_id": "ec89b1f7-1cf2-40eb-91b4-78716093f9ed",
"status": "success",
"task": {
"id": "ec89b1f7-1cf2-40eb-91b4-78716093f9ed",
"state": "success",
"created_at": "2026-02-09T23:15:43.549Z",
"modified_at": "2026-02-09T23:16:39.094Z",
"account_name": "your-account"
},
"data": {
"html": "...",
"markdown": "# Page Title\n\nContent...",
"headers": { ... }
},
"metadata": {
"query_time": "2026-02-09T23:15:43.549Z",
"query_duration": 1877,
"response_parameters": {
"input_url": "https://www.nimbleway.com/blog/post"
},
"driver": "vx6"
},
"status_code": 200
}
```
### Polling endpoints reference
| API | Submit | Check Status | Get Results |
| ------- | ------------------------ | -------------------------- | -------------------------------------------- |
| Extract | `POST /v1/extract/async` | `GET /v1/tasks/{task_id}` | `GET /v1/tasks/{task_id}/results` |
| Agent | `POST /v1/agent/async` | `GET /v1/tasks/{task_id}` | `GET /v1/tasks/{task_id}/results` |
| Crawl | `POST /v1/crawl` | `GET /v1/crawl/{crawl_id}` | `GET /v1/tasks/{task_id}/results` (per page) |
***
## Option 2: Webhooks (Push)
Get notified automatically when your tasks complete. Perfect for event-driven architectures.
Include `callback_url` (or `callback` object for crawl) in your async request.
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
response = nimble.extract_async(
url="https://www.nimbleway.com",
render=True,
formats=["html", "markdown"],
callback_url="https://your-server.com/webhooks/nimble"
)
task_id = response.task_id
print(f"Task submitted: {task_id}")
print("Results will be POSTed to your callback URL when ready")
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const response = await nimble.extractAsync({
url: "https://www.nimbleway.com",
render: true,
formats: ["html", "markdown"],
callback_url: "https://your-server.com/webhooks/nimble"
});
const taskId = response.task_id;
console.log(`Task submitted: ${taskId}`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract/async' \
--header 'Authorization: Bearer YOUR-API-KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.nimbleway.com",
"render": true,
"formats": ["html", "markdown"],
"callback_url": "https://your-server.com/webhooks/nimble"
}'
```
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
response = nimble.extract_async(
url="https://www.nimbleway.com",
render=True,
formats=["html", "markdown"],
callback_url="https://your-server.com/webhooks/nimble"
)
task_id = response.task_id
print(f"Task submitted: {task_id}")
print("Results will be POSTed to your callback URL when ready")
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const response = await nimble.agent.runAsync({
agent: "amazon_pdp",
params: {
asin: "B0DLKFK6LR",
callback_url: "https://your-server.com/webhooks/nimble"
},
});
const taskId = response.task_id;
console.log(`Task submitted: ${taskId}`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract/async' \
--header 'Authorization: Bearer YOUR-API-KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.nimbleway.com",
"render": true,
"formats": ["html", "markdown"],
"callback_url": "https://your-server.com/webhooks/nimble"
}'
```
Crawl uses a `callback` object for advanced webhook options.
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.crawl.run(
url="https://www.nimbleway.com",
limit=100,
callback={
"url": "https://your-server.com/webhooks/nimble",
"headers": {
"X-Custom-Auth": "your-secret-token"
},
"events": ["completed", "failed"]
}
)
print(f"Crawl started: {result.crawl_id}")
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.crawl.run({
url: "https://www.nimbleway.com",
limit: 100,
callback: {
url: "https://your-server.com/webhooks/nimble",
headers: {
"X-Custom-Auth": "your-secret-token"
},
events: ["completed", "failed"]
}
});
console.log(`Crawl started: ${result.crawl_id}`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/crawl' \
--header 'Authorization: Bearer YOUR-API-KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.nimbleway.com",
"limit": 100,
"callback": {
"url": "https://your-server.com/webhooks/nimble",
"headers": { "X-Custom-Auth": "your-secret-token" },
"events": ["completed", "failed"]
}
}'
```
Nimble sends a POST to your callback URL when complete:
```json theme={"system"}
{
"task": {
"id": "8e8cfde8-345b-42b8-b3e2-0c61eb11e00f",
"state": "completed",
"status_code": 200,
"created_at": "2026-01-24T12:36:24.685Z",
"modified_at": "2026-01-24T12:36:24.685Z",
"input": {},
"api_type": "extract"
}
}
```
### Webhook configuration options
| API | Parameter | Type | Description |
| ------- | --------------------- | ------ | ------------------------------------------------------- |
| Extract | `callback_url` | string | Your callback URL |
| Agent | `params.callback_url` | string | Your callback URL |
| Crawl | `callback.url` | string | Your callback URL |
| | `callback.headers` | object | Custom headers for authentication |
| | `callback.metadata` | object | Custom data included in payload |
| | `callback.events` | array | Filter events: `started`, `page`, `completed`, `failed` |
***
## Option 3: Cloud Delivery
Automatically deliver results directly to your cloud storage bucket.
Deliver to any S3 bucket in your AWS account
Deliver to any GCS bucket in your GCP project
Grant Nimble's service account write access to your bucket.
**Nimble Service User ARN:**
```
arn:aws:iam::744254827463:user/webit-uploader
```
Add this bucket policy:
```json theme={"system"}
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "NimbleCloudDelivery",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::744254827463:user/webit-uploader"
},
"Action": [
"s3:PutObject",
"s3:PutObjectACL",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::YOUR_BUCKET_NAME",
"arn:aws:s3:::YOUR_BUCKET_NAME/*"
]
}
]
}
```
Replace `YOUR_BUCKET_NAME` with your actual bucket name.
For KMS-encrypted buckets, add this to your KMS key policy:
```json theme={"system"}
{
"Sid": "NimbleKMSAccess",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::744254827463:user/webit-uploader"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
}
```
**Nimble Service Account:**
```
nimbleway-gcp-storage@nimbleway-gcp.iam.gserviceaccount.com
```
1. Navigate to your bucket in the [Google Cloud Console](https://console.cloud.google.com/storage/browser)
2. Click on the **Permissions** tab
3. Click **Grant Access**
4. Add principal: `nimbleway-gcp-storage@nimbleway-gcp.iam.gserviceaccount.com`
5. Assign role: **Storage Object Creator**
6. Click **Save**
Include `storage_type` and `storage_url` in your request.
#### Cloud delivery parameters
| Parameter | Type | Description |
| --------------------- | ------------ | ----------------------------------------------------- |
| `storage_type` | `s3` \| `gs` | Cloud provider |
| `storage_url` | string | Bucket path with prefix (e.g., `s3://bucket/prefix/`) |
| `storage_compress` | boolean | Enable GZIP compression |
| `storage_object_name` | string | Custom filename (default: task ID) |
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
response = nimble.extract_async(
url="https://www.nimbleway.com",
render=True,
formats=["html", "markdown"],
storage_type="s3",
storage_url="s3://your-bucket/nimble-results/",
storage_compress=True,
storage_object_name="my-result"
)
task_id = response.task_id
print(f"Results will be saved to: s3://your-bucket/nimble-results/my-result.json.gz")
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const response = await nimble.extractAsync({
url: "https://www.nimbleway.com",
render: true,
formats: ["html", "markdown"],
storage_type: "s3",
storage_url: "s3://your-bucket/nimble-results/",
storage_compress: true,
storage_object_name: "my-result"
});
const taskId = response.task_id;
console.log(`Results will be saved to: s3://your-bucket/nimble-results/my-result.json.gz`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract/async' \
--header 'Authorization: Bearer YOUR-API-KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.nimbleway.com",
"render": true,
"formats": ["html", "markdown"],
"storage_type": "s3",
"storage_url": "s3://your-bucket/nimble-results/",
"storage_compress": true,
"storage_object_name": "my-result"
}'
```
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
response = nimble.extract_async(
url="https://www.nimbleway.com",
render=True,
formats=["html", "markdown"],
storage_type="gs",
storage_url="gs://your-bucket/nimble-results/",
storage_object_name="my-result"
)
task_id = response.task_id
print(f"Results will be saved to: gs://your-bucket/nimble-results/my-result.json")
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const response = await nimble.extractAsync({
url: "https://www.nimbleway.com",
render: true,
formats: ["html", "markdown"],
storage_type: "gs",
storage_url: "gs://your-bucket/nimble-results/",
storage_object_name: "my-result"
});
const taskId = response.task_id;
console.log(`Results will be saved to: gs://your-bucket/nimble-results/my-result.json`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract/async' \
--header 'Authorization: Bearer YOUR-API-KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.nimbleway.com",
"render": true,
"formats": ["html", "markdown"],
"storage_type": "gs",
"storage_url": "gs://your-bucket/nimble-results/",
"storage_object_name": "my-result"
}'
```
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
response = nimble.agent.run_async(
agent="amazon_pdp",
params={
"asin": "B0DLKFK6LR",
"storage_type": "s3",
"storage_url": "s3://your-bucket/nimble-results/",
"storage_compress": True,
"storage_object_name": "my-result"
}
)
task_id = response.task_id
print(f"Results will be saved to: s3://your-bucket/nimble-results/my-result.json.gz")
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const response = await nimble.agent.runAsync({
agent: "amazon_pdp",
params: {
asin: "B0DLKFK6LR",
storage_type: "s3",
storage_url: "s3://your-bucket/nimble-results/",
storage_compress: true,
storage_object_name: "my-result"
}
});
const taskId = response.task_id;
console.log(`Results will be saved to: s3://your-bucket/nimble-results/my-result.json.gz`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/agent/async' \
--header 'Authorization: Bearer YOUR-API-KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"agent": "amazon_pdp",
"params": {
"asin": "B0DLKFK6LR",
"storage_type": "s3",
"storage_url": "s3://your-bucket/nimble-results/",
"storage_compress": true,
"storage_object_name": "my-result"
}
}'
```
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
response = nimble.agent.run_async(
agent="amazon_pdp",
params={
"asin": "B0DLKFK6LR",
"storage_type": "gs",
"storage_url": "gs://your-bucket/nimble-results/",
"storage_object_name": "my-result"
}
)
task_id = response.task_id
print(f"Results will be saved to: gs://your-bucket/nimble-results/my-result.json")
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const response = await nimble.agent.runAsync({
agent: "amazon_pdp",
params: {
asin: "B0DLKFK6LR",
storage_type: "gs",
storage_url: "gs://your-bucket/nimble-results/",
storage_object_name: "my-result"
}
});
const taskId = response.task_id;
console.log(`Results will be saved to: gs://your-bucket/nimble-results/my-result.json`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/agent/async' \
--header 'Authorization: Bearer YOUR-API-KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"agent": "amazon_pdp",
"params": {
"asin": "B0DLKFK6LR",
"storage_type": "gs",
"storage_url": "gs://your-bucket/nimble-results/",
"storage_object_name": "my-result"
}
}'
```
When complete, results are written to your bucket as `{task_id}.json` (or `.json.gz` if compressed).
***
## Comparison
| Feature | Polling | Webhooks | Cloud Delivery |
| --------------------------- | ---------------------------- | ----------------- | --------------------- |
| **Setup complexity** | None | Requires endpoint | Requires bucket setup |
| **Real-time notifications** | No (you poll) | Yes | No |
| **Automatic storage** | No | No | Yes |
| **Best for** | Simple integrations, testing | Event-driven apps | Data pipelines ETLs |
| **Infrastructure needed** | None | Web server | Cloud storage bucket |
### Combining methods
You can combine delivery methods for redundancy:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Receive webhook AND store in S3
response = nimble.extract_async(
url="https://www.nimbleway.com",
formats=["html", "markdown"],
callback_url="https://your-server.com/webhooks/nimble",
storage_type="s3",
storage_url="s3://your-bucket/results/"
)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Receive webhook AND store in S3
const response = await nimble.extractAsync({
url: "https://www.nimbleway.com",
formats: ["html", "markdown"],
callback_url: "https://your-server.com/webhooks/nimble",
storage_type: "s3",
storage_url: "s3://your-bucket/results/",
});
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract/async' \
--header 'Authorization: Bearer YOUR-API-KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.nimbleway.com",
"formats": ["html", "markdown"],
"callback_url": "https://your-server.com/webhooks/nimble",
"storage_type": "s3",
"storage_url": "s3://your-bucket/results/"
}'
```
***
## Best Practices
* **Check status first** - Use `/tasks/{id}` before fetching full results -
**Use reasonable intervals** - Poll every 2-5 seconds, not continuously -
**Handle rate limits** - Implement retry logic for 429 responses - **Set
timeouts** - Most tasks complete within seconds to minutes
* **Use HTTPS** - Always use secure endpoints - **Verify authenticity** -
Use custom headers for authentication - **Respond quickly** - Return 200 OK
immediately, process async - **Handle retries** - Nimble retries failed
deliveries
* **Use prefixes** - Organize by date, project, or type - **Enable
compression** - Use `storage_compress: true` for large files - **Set
lifecycle policies** - Auto-delete old files to manage costs - **Use custom
names** - `storage_object_name` for meaningful filenames
## Next Steps
Learn about async extraction options
Deep website crawling with async delivery
Browse available search agents
Understand API rate limit
# Compliance
Source: https://docs.nimbleway.com/nimble-sdk/admin/compliance
# Legacy Docs
Source: https://docs.nimbleway.com/nimble-sdk/admin/legacy-docs
# Pricing
Source: https://docs.nimbleway.com/nimble-sdk/admin/pricing
Flexible usage-based pricing for Nimble SDK
Nimble offers two ways to access the platform: **API pricing** for direct, per-request access, and **Data Services plans** for managed, production-scale workloads.
**Free Trial:** Get started with 5,000 free web pages. No credit card
required. [Start Building Now](https://online.nimbleway.com/signup)
***
## API Pricing
Use any Nimble API without a commitment. Only successful requests are charged.
### Extract, Crawl & Map APIs
Priced per 1,000 URLs based on the rendering driver:
* **Map** always uses the `VX6` driver.
* **Crawl** is billed as the sum of all `Extract` requests within the crawl.
| Extract Driver | Description | PAYG Price |
| -------------- | --------------------------- | ---------------- |
| `VX6` | Standard — no JS rendering | \$0.90 / 1K URLs |
| `VX8` | JS rendering | \$1.30 / 1K URLs |
| `VX10` | JS rendering + Stealth Mode | \$1.45 / 1K URLs |
Nimble selects the optimal driver automatically, selecting driver manually may
cause blocks or empty responses
### Agent API
Priced per 1,000 URLs based on the rendering driver:
#### Community & Custom Agents
Web Search Agents (WSA) you create in Studio or from the community gallery:
| Agent Driver | Description | PAYG Price |
| ------------ | --------------------------- | ---------------- |
| `WSA-6` | Standard — no JS rendering | \$0.99 / 1K URLs |
| `WSA-8` | JS rendering | \$1.45 / 1K URLs |
| `WSA-10` | JS rendering + Stealth Mode | \$1.60 / 1K URLs |
#### Nimble-Maintained Agents
Pre-built Web Search Agents (WSA), maintained by Nimble:
| Agent Driver | Description | PAYG Price |
| ------------ | --------------------------- | ---------------- |
| `WSA-6M` | Standard — no JS rendering | \$1.08 / 1K URLs |
| `WSA-8M` | JS rendering | \$1.55 / 1K URLs |
| `WSA-10M` | JS rendering + Stealth Mode | \$1.75 / 1K URLs |
Nimble selects the optimal driver automatically, selecting driver manually may
cause blocks or empty responses
### Search API
| Operation | PAYG Price |
| --------------------- | -------------------------------------------------- |
| Search | \$1.00 / 1K inputs (up to 100 results per request) |
| Answer (AI-generated) | \$4.00 / 1K inputs |
Deep Mode search also includes all `Extract` and/or `Agent` API costs. Total
cost varies by configuration.
### Proxy API
| Product | PAYG Price |
| ----------------- | ----------- |
| Residential Proxy | \$5.30 / GB |
### Custom Rates
Custom API pricing for high-scale workloads. Includes:
* **Volume discounts:** lower per-request rates at scale
* **Multi-year pricing protection:** rate locks and long-term discounts
* **Product bundling discounts:** combine APIs for better rates
* **Custom concurrent sessions:** beyond standard limits
* **Dedicated support** and SLA options
To discuss custom API pricing for your use case, please [Contact
Sales](https://nimbleway.com/contact-general/)
***
## Data Services Plans
Managed plans for teams running agents and data pipelines at scale. Billed annually.
| | **Startup** | **Scale** | **Professional** | **Enterprise** |
| -------------- | ----------- | ---------- | ---------------- | -------------- |
| **Price** | \$2,000/mo | \$7,500/mo | \$15,000/mo | Custom |
| **Agents** | 10 | 20 | Unlimited | Unlimited |
| **Credits** | 500K pages | 3M pages | 8M pages | Custom |
| **Concurrent** | 5 | 10 | 30 | Custom |
| **Storage** | 30 days | 90 days | 365 days | Custom |
* 10 agents
* 500,000 web page credits
* 5 concurrent agents
* 30 days data storage
* Custom agent ETL
* MCP integration
* 20 agents
* 3,000,000 web page credits
* 10 concurrent agents
* 90 days data storage
* Custom agent ETL
* MCP integration
* Data Lake integration
* City-level agent geo-targeting
* SLA & Priority support
* Unlimited agents
* 8,000,000 web page credits
* 30 concurrent agents
* 365 days data storage
* Data Lake integration
* City-level agent geo-targeting
* SLA & Priority support
Everything in Professional, plus:
* Advanced security features
* Custom credit volumes and concurrency limits
* Dedicated support
[Contact Sales](https://nimbleway.com/contact-general/) to discuss your requirements.
***
## Understanding Drivers
Drivers are tiers of complexity --> You only pay for the capability your target site actually requires.
Nimble selects the optimal driver automatically, so simple pages use the cheapest tier and complex, protected pages escalate only when needed.
You can override the driver manually on the `/extract`, `/crawl`, and `/agent` APIs using the `driver` parameter.
No JavaScript execution. Fast and lightweight.
**Use when:** The page is static HTML: articles, docs, APIs, JSON endpoints.
**Not suitable for:** JS-rendered pages, browser actions, network capture.
Full JavaScript execution for dynamic content.
**Use when:** The page requires JavaScript to load: SPAs, lazy-loaded content, browser actions, network capture.
Full JS rendering with advanced anti-bot fingerprinting and evasion.
**Use when:** The site actively blocks scrapers: Cloudflare, PerimeterX, or other bot protection layers.
Using `VX6`, `VX8`, or `VX10` on an **Agent** request is automatically mapped to the equivalent agent driver.
| Alias | Community & Custom | Nimble-Maintained |
| ------ | ------------------ | ----------------- |
| `VX6` | `WSA-6` | `WSA-6M` |
| `VX8` | `WSA-8` | `WSA-8M` |
| `VX10` | `WSA-10` | `WSA-10M` |
***
## Billing FAQ
Pay-as-you-go usage is billed monthly by credit card. Data Services plans
are billed annually. Only successful requests count toward your usage.
Additional usage is billed at pay-as-you-go rates on your next invoice.
Yes. Plan changes take effect on your next billing cycle.
Credits roll over within your billing cycle but expire at the end of each
month.
[Contact our sales team](https://nimbleway.com/contact-general/) for custom
rates based on your volume and requirements.
***
## Get Started
Get 5,000 free pages to test the platform
Discuss Data Services plans or custom pricing
# Rate Limits
Source: https://docs.nimbleway.com/nimble-sdk/admin/rate-limits
Technical specifications, rate limits, and API constraints
Understanding API limitations and specifications helps you optimize performance, plan capacity, and avoid throttling. This guide covers rate limits, driver capabilities, request constraints, and best practices.
## Overview
Nimble's API implements tiered specifications based on:
* **Driver selection**: Different drivers have different rate limits
* **Request complexity**: Complex operations may have additional constraints
* **Resource usage**: Fair usage policies ensure platform stability
## Drivers
Nimble offers different drivers optimized for various use cases:
| **Driver** | **Description** | **Best For** |
| ---------- | ------------------------------- | ------------------------------ |
| `vx6` | HTTP requests without rendering | Static pages, simple HTML |
| `vx8` | JavaScript rendering | Dynamic content, AJAX |
| `vx10` | Stealth browser mode | Protected sites, complex sites |
Each driver has different pricing and rate limits. Higher-tier drivers cost more per request.
## Rate Limits
### Default rate limits by driver
All accounts have the following default rate limits:
| **Driver** | **Rate Limit** |
| -------------------- | ------------------ |
| `vx6`, `vx8`, `vx10` | 83 QPS (5,000 QPM) |
**Need higher limits?** Reach out to your CS or open a via a [Support Ticket](https://portal.usepylon.com/nimble) to discuss custom rate limits based on your requirements.
### Response headers
Every response includes metadata headers:
```
ratelimit-limit: 20
ratelimit-remaining: 15
x-task-id: 8e8cfde8-345b-42b8-b3e2-0c61eb11e00f
```
Use these headers to:
* Monitor rate limit usage
* Track request IDs for debugging
* Optimize driver selection
* Measure performance
### Handling rate limits
When you exceed rate limits, the API returns a 429 status code:
```json theme={"system"}
{
"status": "failed",
"msg": "Rate limit exceeded"
}
```
**Best practices:**
* Implement exponential backoff on 429 responses
* Use the `retry_after` value to schedule next request
* Monitor rate limit headers in responses
* Batch requests when possible
* Use lower-tier drivers when sufficient
## HTTP status codes
### Success codes
| Code | Status | Description |
| :------ | :----- | :--------------------------------------------------- |
| **200** | OK | Request succeeded and data was returned successfully |
### Client error codes
| Code | Status | Description |
| :------ | :---------------- | :--------------------------------------------------------------- |
| **400** | Bad Request | Invalid URL, malformed parameters, or missing required fields |
| **401** | Unauthorized | Account doesn't exist, invalid API key, or missing credentials |
| **402** | Payment Required | No budget, limit reached, trial expired, or trial quota finished |
| **403** | Forbidden | Account blocked or not activated |
| **429** | Too Many Requests | Rate limit exceeded for your plan |
### Server error codes
| Code | Status | Description |
| :------ | :-------------------- | :-------------------------------------- |
| **500** | Internal Server Error | Unexpected server-side error occurred |
| **501** | Not Implemented | Proxy service encountered an error |
| **555** | Request Timeout | Request exceeded maximum execution time |
Nimble automatically retries failed requests before returning a final failure status (500)
# Agents Gallery
Source: https://docs.nimbleway.com/nimble-sdk/agentic/agent-gallery
Browse, search, and inspect available Web Search Agents
Nimble **Agent Discovery APIs** help you find and understand available agents before using them. Browse agents by vertical, search by domain, and inspect detailed schemas to understand input parameters and output fields.
**Can't find what you need?** Create a custom agent for any website using the
[Agentic Studio](/nimble-sdk/agentic/studio) - no coding required, just
describe what you want in natural language.
All public agents are **maintained by Nimble** - we monitor them 24/7 and
automatically update them when websites change their structure.
Browse agents visually with previews, examples, and interactive documentation.
## When to Use
Use agent discovery when you need to:
* **Browse available agents** - See what platforms are supported
* **Filter by vertical** - Find agents for specific industries (e-commerce, search, social)
* **Inspect agent details** - Understand input parameters and output schema
* **Check capabilities** - Verify localization and pagination support
## Two Ways to Explore
Prefer a visual interface? Browse agents with previews, live demos, and
exportable code snippets at the [Agent
Gallery](https://online.nimbleway.com/pipeline-gallery) in Nimble Platform.
***
## List Agents API
Browse and search the agent catalog.
`GET https://sdk.nimbleway.com/v1/agents`
### Parameters
| Parameter | Type | Description | Required |
| --------- | ------- | ---------------------------------------------------- | -------- |
| `privacy` | Enum | Filter by privacy level (`all`, `public`, `private`) | No |
| `search` | String | Filter agents by keyword. | No |
| `offset` | Integer | Pagination offset (default: `0`) | No |
| `limit` | Integer | Number of results per page (default: `100`) | No |
### Response Schema
Each agent in the response contains:
| Field | Type | Description |
| -------------- | ------- | -------------------------------------------------------------------------------------- |
| `name` | string | Unique agent identifier (use this in API calls) |
| `display_name` | string | Human-readable agent name |
| `description` | string | What the agent does |
| `is_public` | boolean | Whether the agent is publicly available |
| `managed_by` | string | Who maintains this agent: `nimble` (public), `community` (public), or `self` (private) |
| `vertical` | string | Industry vertical (e.g., "Ecommerce", "Search") |
| `entity_type` | string | Page type (e.g., "Product Detail Page", "SERP") |
| `domain` | string | Target website domain |
### Usage Examples
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# List all public agents
agents = nimble.agent.list(privacy="public")
for agent in agents:
print(f"{agent.name}: {agent.display_name}")
print(f" Domain: {agent.domain}")
print(f" Vertical: {agent.vertical}")
print(f" Type: {agent.entity_type}")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// List all public agents
const agents = await nimble.agent.list({ privacy: "public" });
agents.forEach((agent) => {
console.log(`${agent.name}: ${agent.display_name}`);
console.log(` Domain: ${agent.domain}`);
console.log(` Vertical: ${agent.vertical}`);
console.log(` Type: ${agent.entity_type}`);
});
```
```bash cURL theme={"system"}
curl -X GET 'https://sdk.nimbleway.com/v1/agents?privacy=public' \
-H 'Authorization: Bearer YOUR-API-KEY'
```
### Response Example
```json theme={"system"}
[
{
"name": "amazon_pdp",
"is_public": true,
"display_name": "Amazon Product Page",
"description": "Extract structured data from Amazon product detail pages including pricing, reviews, specifications, and availability.",
"vertical": "Ecommerce",
"entity_type": "Product Detail Page (PDP)",
"domain": "www.amazon.com"
},
{
"name": "amazon_serp",
"is_public": true,
"display_name": "Amazon Search Results",
"description": "Extract product listings from Amazon search results pages based on a keyword query.",
"vertical": "Ecommerce",
"entity_type": "Search Engine Results Page (SERP)",
"domain": "www.amazon.com"
},
{
"name": "walmart_pdp",
"is_public": true,
"display_name": "Walmart Product Page",
"description": "Extract structured data from Walmart product detail pages including pricing, reviews, and variants.",
"vertical": "Ecommerce",
"entity_type": "Product Detail Page (PDP)",
"domain": "www.walmart.com"
},
{
"name": "google_search",
"is_public": true,
"display_name": "Google Search Results",
"description": "Extract structured data from Google Search Results Pages (SERPs) including organic results, ads, and featured snippets.",
"vertical": "Search Engine",
"entity_type": "Search Engine Results Page (SERP)",
"domain": "www.google.com"
}
]
```
***
## Get Agent Details API
Get comprehensive information about a specific agent, including input parameters and output schema.
```GET https://sdk.nimbleway.com/v1/agents/{agent_name} theme={"system"}
```
### Parameters
| Parameter | Type | Description | Required |
| ------------ | ------ | ----------------------------------- | -------- |
| `agent_name` | string | The agent name (e.g., `amazon_pdp`) | Yes |
### Response Schema
| Field | Type | Description |
| ------------------ | ------- | -------------------------------------------------------------------------------------- |
| `name` | string | Unique agent identifier |
| `display_name` | string | Human-readable agent name |
| `description` | string | What the agent does |
| `is_public` | boolean | Whether the agent is publicly available |
| `managed_by` | string | Who maintains this agent: `nimble` (public), `community` (public), or `self` (private) |
| `vertical` | string | Industry vertical |
| `entity_type` | string | Page type |
| `domain` | string | Target website domain |
| `input_properties` | array | Input parameters for the agent (see below) |
| `output_schema` | object | JSON schema describing output fields |
| `feature_flags` | object | Supported capabilities (localization, pagination) |
#### Input Properties
Each item in `input_properties` contains:
| Field | Type | Description |
| ------------- | ------- | ----------------------------------- |
| `name` | string | Parameter name |
| `type` | string | Data type (string, number, boolean) |
| `description` | string | What the parameter does |
| `required` | boolean | Whether the parameter is required |
| `default` | string | Default value if not provided |
| `examples` | array | Example values |
| `rules` | array | Validation rules |
#### Feature Flags
| Flag | Type | Description |
| --------------------------- | ------- | -------------------------------------------- |
| `is_localization_supported` | boolean | Supports ZIP code for location-specific data |
| `is_pagination_supported` | boolean | Supports paginated results |
### Usage Examples
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Get agent details
agent = nimble.agent.get("amazon_pdp")
print(f"Agent: {agent.display_name}")
print(f"Description: {agent.description}")
print(f"Domain: {agent.domain}")
# Check feature flags
flags = agent.feature_flags
print(f"\nCapabilities:")
print(f" Localization: {'Yes' if flags.is_localization_supported else 'No'}")
print(f" Pagination: {'Yes' if flags.is_pagination_supported else 'No'}")
# List input parameters
print(f"\nInput Parameters:")
for param in agent.input_properties:
required = "required" if param.required else "optional"
print(f" {param.name} ({param.type}) - {required}")
print(f" {param.description}")
if param.examples:
print(f" Examples: {', '.join(param.examples)}")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Get agent details
const agent = await nimble.agent.get("amazon_pdp");
console.log(`Agent: ${agent.display_name}`);
console.log(`Description: ${agent.description}`);
console.log(`Domain: ${agent.domain}`);
// Check feature flags
const flags = agent.feature_flags;
console.log("\nCapabilities:");
console.log(
` Localization: ${flags.is_localization_supported ? "Yes" : "No"}`,
);
console.log(` Pagination: ${flags.is_pagination_supported ? "Yes" : "No"}`);
// List input parameters
console.log("\nInput Parameters:");
agent.input_properties.forEach((param) => {
const required = param.required ? "required" : "optional";
console.log(` ${param.name} (${param.type}) - ${required}`);
console.log(` ${param.description}`);
if (param.examples?.length) {
console.log(` Examples: ${param.examples.join(", ")}`);
}
});
```
```bash cURL theme={"system"}
curl -X GET 'https://sdk.nimbleway.com/v1/agents/amazon_pdp' \
-H 'Authorization: Bearer YOUR-API-KEY'
```
### Response Example
```json theme={"system"}
{
"name": "amazon_pdp",
"is_public": true,
"display_name": "Amazon Product Page",
"description": "Extract structured data from Amazon product detail pages including pricing, reviews, specifications, variants, and availability.",
"vertical": "Ecommerce",
"entity_type": "Product Detail Page (PDP)",
"domain": "www.amazon.com",
"input_properties": [
{
"name": "asin",
"required": true,
"type": "string",
"description": "Amazon Standard Identification Number (ASIN) - the unique 10-character product identifier",
"rules": ["Must be exactly 10 alphanumeric characters"],
"examples": ["B08N5WRWNW", "B0DLKFK6LR"],
"default": null
},
{
"name": "zip_code",
"required": false,
"type": "string",
"description": "ZIP code for location-specific pricing and availability",
"rules": ["5-digit US ZIP code"],
"examples": ["90210", "10001"],
"default": "90210"
}
],
"output_schema": {
"asin": { "type": "string", "description": "Product ASIN" },
"product_title": { "type": "string", "description": "Full product name" },
"brand": { "type": "string", "description": "Product brand" },
"web_price": { "type": "number", "description": "Current selling price" },
"list_price": {
"type": "number",
"description": "Original price before discount"
},
"average_of_reviews": {
"type": "number",
"description": "Average rating (0-5)"
},
"number_of_reviews": {
"type": "number",
"description": "Total review count"
},
"availability": { "type": "boolean", "description": "Whether in stock" },
"image_url": { "type": "string", "description": "Main product image URL" }
},
"feature_flags": {
"is_localization_supported": true,
"is_pagination_supported": false
}
}
```
***
## Available Agents by Vertical
### E-commerce
| Agent | Display Name | Domain | Localization | Pagination |
| ----------------- | -------------------- | --------------------------------------------- | ------------ | ---------- |
| `amazon_pdp` | Amazon Product Page | [www.amazon.com](http://www.amazon.com) | Yes | No |
| `amazon_serp` | Amazon Search | [www.amazon.com](http://www.amazon.com) | Yes | Yes |
| `amazon_category` | Amazon Category | [www.amazon.com](http://www.amazon.com) | No | Yes |
| `walmart_pdp` | Walmart Product Page | [www.walmart.com](http://www.walmart.com) | Yes | No |
| `walmart_search` | Walmart Search | [www.walmart.com](http://www.walmart.com) | Yes | Yes |
| `target_pdp` | Target Product Page | [www.target.com](http://www.target.com) | Yes | No |
| `best_buy_pdp` | Best Buy Product | [www.bestbuy.com](http://www.bestbuy.com) | Yes | No |
| `home_depot_pdp` | Home Depot Product | [www.homedepot.com](http://www.homedepot.com) | Yes | No |
### Search Engines
| Agent | Display Name | Domain | Localization | Pagination |
| -------------------- | --------------------- | --------------------------------------- | ------------ | ---------- |
| `google_search` | Google Search Results | [www.google.com](http://www.google.com) | Yes | Yes |
| `google_maps_search` | Google Maps Search | maps.google.com | Yes | Yes |
| `google_search_aio` | Google AI Overview | [www.google.com](http://www.google.com) | Yes | No |
### Social Media
| Agent | Display Name | Domain | Localization | Pagination |
| ---------------- | -------------- | ------------------------------------------- | ------------ | ---------- |
| `tiktok_account` | TikTok Account | [www.tiktok.com](http://www.tiktok.com) | No | Yes |
| `facebook_page` | Facebook Page | [www.facebook.com](http://www.facebook.com) | No | No |
| `youtube_shorts` | YouTube Shorts | [www.youtube.com](http://www.youtube.com) | No | Yes |
### LLM Platforms
| Agent | Display Name | Domain | Localization | Pagination |
| ------------ | ----------------- | --------------------------------------------- | ------------ | ---------- |
| `chatgpt` | ChatGPT Responses | chatgpt.com | No | No |
| `gemini` | Gemini Responses | gemini.google.com | No | No |
| `perplexity` | Perplexity | [www.perplexity.ai](http://www.perplexity.ai) | No | No |
| `grok` | Grok Responses | grok.com | No | No |
***
## Common Patterns
### Search Agents by Keyword
Use the `search` query parameter to find agents matching a term across `display_name`, `vertical`, and `domain`:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
agents = nimble.agent.list(search="amazon")
for agent in agents:
print(f"{agent.name}: {agent.display_name} ({agent.domain})")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const agents = await nimble.agent.list({ search: "amazon" });
agents.forEach((agent) => {
console.log(`${agent.name}: ${agent.display_name} (${agent.domain})`);
});
```
```bash cURL theme={"system"}
curl -X GET 'https://sdk.nimbleway.com/v1/agents?search=amazon' \
-H 'Authorization: Bearer YOUR-API-KEY'
```
### Filter Agents by Vertical
Find all agents for a specific industry:
```python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Get all agents
agents = nimble.agent.list(privacy="public")
# Filter by vertical
ecommerce_agents = [
agent for agent in agents
if agent.vertical == 'Ecommerce'
]
print(f"Found {len(ecommerce_agents)} e-commerce agents:")
for agent in ecommerce_agents:
print(f" {agent.name}: {agent.display_name} ({agent.domain})")
```
### Check Localization Support
Verify an agent supports location-specific data:
```python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
agent = nimble.agent.get("amazon_pdp")
if agent.feature_flags.is_localization_supported:
print("This agent supports localization!")
print("Pass zip_code parameter for location-specific pricing.")
else:
print("This agent does not support localization.")
```
### Get Required Parameters
Find which parameters are required before calling an agent:
```python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
agent = nimble.agent.get("amazon_pdp")
required_params = [
p for p in agent.input_properties
if p.required
]
optional_params = [
p for p in agent.input_properties
if not p.required
]
print("Required parameters:")
for p in required_params:
examples = ', '.join(p.examples) if p.examples else ''
print(f" {p.name}: {p.description}")
if examples:
print(f" Examples: {examples}")
print("\nOptional parameters:")
for p in optional_params:
default = p.default if p.default else 'none'
print(f" {p.name}: {p.description} (default: {default})")
```
### Validate Parameters Before Calling
Check parameters match the expected schema:
```python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
def validate_params(agent_name, params):
"""Validate params against agent input_properties"""
agent = nimble.agent.get(agent_name)
errors = []
# Build lookup of input properties
props = {p.name: p for p in agent.input_properties}
# Check required fields
for prop_name, prop in props.items():
if prop.required and prop_name not in params:
errors.append(f"Missing required parameter: {prop_name}")
# Check for unknown parameters
for param_name in params:
if param_name not in props:
errors.append(f"Unknown parameter: {param_name}")
return errors
# Validate before calling
errors = validate_params("amazon_pdp", {"asin": "B08N5WRWNW"})
if errors:
print("Validation errors:")
for error in errors:
print(f" - {error}")
else:
print("Parameters are valid!")
```
***
## Next Steps
Explore endpoints, request parameters, and response schemas for the Agents API
Learn how to call agents in your code
Build your own agent with natural language
Browse agents visually
# Search Agents
Source: https://docs.nimbleway.com/nimble-sdk/agentic/agents
Pre-built extraction agents for popular platforms - zero configuration required
Nimble **Web Search Agents (WSA)** are ready-to-use extraction agents for popular websites like Amazon, Google, LinkedIn, and hundreds more. No CSS selectors or scraping expertise required - just provide the agent name and parameters, and get structured data instantly.
## Quick Start
### Example Request
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.agent.run(
agent="amazon_pdp",
params={
"asin": "B0DLKFK6LR"
}
)
parsed = result.data.parsing["parsed"]
print(f"Product: {parsed['product_title']}")
print(f"Price: ${parsed['web_price']}")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.agent.run({
agent: "amazon_pdp",
params: {
asin: "B0DLKFK6LR",
},
});
const parsed = result.data.parsing.parsed;
console.log(`Product: ${parsed.product_title}`);
console.log(`Price: $${parsed.web_price}`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/agents/run' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"agent": "amazon_pdp",
"params": {
"asin": "B0DLKFK6LR"
}
}'
```
### Example Response
```json theme={"system"}
{
"url": "https://www.amazon.com/dp/B08N5WRWNW",
"task_id": "b1fa7943-cba5-4ec2-a88c-4d2d6799c794",
"status": "success",
"data": {
"html": "...",
"parsing": {
"asin": "B08N5WRWNW",
"product_title": "Apple AirPods Pro (2nd Generation)",
"brand": "Apple",
"web_price": 249.0,
"list_price": 279.0,
"average_of_reviews": 4.7,
"number_of_reviews": 125432,
"availability": true
}
},
"status_code": 200
}
```
## How it works
Choose an agent by name (e.g., `amazon_pdp`, `google_search`) and pass the
required parameters like product ID, search query, or URL
The agent fetches the page, handles anti-bot protection, and extracts data
using battle-tested selectors maintained by Nimble
Get clean, normalized JSON with consistent field names - ready to use in
your application immediately
## Two types of agents
\ **Maintained by Nimble** - Gallery of pre-built agents for popular
websites. \ \ Battle-tested, auto-healing, and updated 24/7 when sites
change. Browse the [Gallery](/nimble-sdk/agentic/agent-gallery).
\ **Created by you** - Build agents for any website using the [Agentic
Studio](/nimble-sdk/agentic/studio). \ \ No coding required - just describe
what you need in natural language.
## Parameters
Supported input parameters:
The name of the pre-built agent to use. Each agent is designed for a specific platform or data type.
**Popular agents:**
* `amazon_pdp` - Amazon product pages
* `amazon_serp` - Amazon search results
* `google_search` - Google search results
* `google_maps_search` - Google Maps locations
* `walmart_pdp` - Walmart products
* `chatgpt` - ChatGPT prompt results
* `perplexity` - Perplexity prompt results
[Browse all agents →](/nimble-sdk/agentic/agent-gallery)
Agent-specific parameters that tell the agent what data to fetch. Each agent has different requirements.
**Common param types:**
* Product IDs (ASINs, SKUs)
* Search queries
* URLs or usernames
* Page numbers for pagination
**Example:**
```json theme={"system"}
{
"asin": "B08N5WRWNW"
}
```
Enable location-based pricing and availability. **Required** when passing `zip_code` or `store_id` in params.
Only available for agents that support localization (check agent details).
**Example:**
```json theme={"system"}
{
"agent": "amazon_pdp",
"localization": true,
"params": {
"asin": "B08N5WRWNW",
"zip_code": "90210"
}
}
```
Each agent has unique parameter requirements. Check the [Agent
Gallery](/nimble-sdk/agentic/agent-gallery) for exact parameters for each
agent.
## Usage
### E-commerce product extraction
Extract product data from Amazon, Walmart, and other retailers:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Amazon product
result = nimble.agent.run(
agent="amazon_pdp",
params={
"asin": "B08N5WRWNW"
}
)
parsed = result.data.parsing["parsed"]
print(f"Product: {parsed['product_title']}")
print(f"Price: ${parsed['web_price']}")
print(f"Rating: {parsed['average_of_reviews']}")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Amazon product
const result = await nimble.agent.run({
agent: "amazon_pdp",
params: {
asin: "B08N5WRWNW",
},
});
const parsed = result.data.parsing.parsed;
console.log(`Product: ${parsed.product_title}`);
console.log(`Price: $${parsed.web_price}`);
console.log(`Rating: ${parsed.average_of_reviews}`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/agents/run' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"agent": "amazon_pdp",
"params": {
"asin": "B08N5WRWNW"
}
}'
```
### Search results extraction
Get search results from Google, Amazon, and other platforms:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Amazon search
result = nimble.agent.run(
agent="amazon_serp",
params={
"keyword": "wireless headphones"
}
)
products = result.data.parsing["parsed"]
print(f"Found {len(products)} products")
for product in products:
print(f"- {product['product_name']}: ${product['price']}")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Amazon search
const result = await nimble.agent.run({
agent: "amazon_serp",
params: {
keyword: "wireless headphones",
},
});
const products = result.data.parsing.parsed;
console.log(`Found ${products.length} products`);
products.forEach((product) => {
console.log(`- ${product.product_name}: $${product.price}`);
});
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/agents/run' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"agent": "amazon_serp",
"params": {
"keyword": "wireless headphones"
}
}'
```
### Google Maps extraction
Find businesses and locations:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.agent.run(
agent="google_maps_search",
params={
"query": "coffee shops near Times Square"
}
)
parsed = result.data.parsing["parsed"]
for place in parsed["entities"]["SearchResult"]:
print(f"- {place['title']} ({place['rating']} stars)")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.agent.run({
agent: "google_maps_search",
params: {
query: "coffee shops near Times Square",
},
});
const parsed = result.data.parsing.parsed;
parsed.entities.SearchResult.forEach((place) => {
console.log(`- ${place.title} (${place.rating} stars)`);
});
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/agents/run' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"agent": "google_maps_search",
"params": {
"query": "coffee shops near Times Square"
}
}'
```
### LLM platform extraction
Get responses from AI platforms like ChatGPT and Perplexity:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.agent.run(
agent="chatgpt",
params={
"prompt": "What are the best practices for web scraping?"
}
)
parsed = result.data.parsing["parsed"]
print(parsed["response"])
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.agent.run({
agent: "chatgpt",
params: {
prompt: "What are the best practices for web scraping?",
},
});
console.log(result.data.parsing.parsed.response);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/agents/run' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"agent": "chatgpt",
"params": {
"prompt": "What are the best practices for web scraping?"
}
}'
```
### Localized extraction
Get location-specific pricing and availability:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Get New York pricing
result = nimble.agent.run(
agent="amazon_pdp",
localization=True,
params={
"asin": "B08N5WRWNW",
"zip_code": "10001"
}
)
parsed = result.data.parsing["parsed"]
print(f"Price in NYC: ${parsed['web_price']}")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Get New York pricing
const result = await nimble.agent.run({
agent: "amazon_pdp",
localization: true,
params: {
asin: "B08N5WRWNW",
zip_code: "10001",
},
});
console.log(`Price in NYC: $${result.data.parsing.parsed.web_price}`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/agents/run' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"agent": "amazon_pdp",
"localization": true,
"params": {
"asin": "B08N5WRWNW",
"zip_code": "10001"
}
}'
```
### Async extraction
Run agent extractions asynchronously:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
response = nimble.agent.run_async(
agent="amazon_pdp",
params={"asin": "B0DLKFK6LR"}
)
task_id = response.task_id
print(f"Task submitted: {task_id}")
# Poll for completion
import time
while True:
my_task = nimble.tasks.get(task_id)
print(f"Status: {my_task.task.state}")
if my_task.state == "success":
break
elif my_task.state == "failed":
print(f"Task failed: {status.error}")
break
time.sleep(15)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const response = await nimble.agent.runAsync({
agent: "amazon_pdp",
params: { asin: "B0DLKFK6LR" },
});
const taskId = response.task_id;
console.log(`Task submitted: ${taskId}`);
// Poll for completion
while (true) {
const myTask = await nimble.tasks.get(taskId);
console.log(`Status: ${myTask.task.state}`);
if (myTask.state === "success") break;
if (myTask.state === "failed") {
console.log(`Task failed: ${status.error}`);
break;
}
await new Promise((resolve) => setTimeout(resolve, 15000));
}
```
```bash cURL theme={"system"}
# Submit async extraction
curl -X POST 'https://sdk.nimbleway.com/v1/agent/async' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"agent": "amazon_pdp",
"params": {"asin": "B08N5WRWNW"}
}'
# Response includes task_id
# {"task": {"id": "abc123..."}}
# Check status
curl 'https://sdk.nimbleway.com/v1/tasks/{task_id}' \
--header 'Authorization: Bearer '
# Get results when completed
curl 'https://sdk.nimbleway.com/v1/tasks/{task_id}/results' \
--header 'Authorization: Bearer '
```
Async mode supports polling, callbacks and cloud storage
## Agent Gallery
Browse pre-built agents **maintained by Nimble** for popular platforms:
Browse all agents with interactive documentation and live testing
### E-commerce
| Agent | Platform | Description |
| ---------------- | -------- | --------------------------------- |
| `amazon_pdp` | Amazon | Product details, pricing, reviews |
| `amazon_serp` | Amazon | Search results with products |
| `walmart_pdp` | Walmart | Product details and pricing |
| `walmart_search` | Walmart | Search results |
| `target_pdp` | Target | Product details |
| `best_buy_pdp` | Best Buy | Product details |
### Search Engines
| Agent | Platform | Description |
| -------------------- | ----------- | ------------------------------- |
| `google_search` | Google | Search results with snippets |
| `google_maps_search` | Google Maps | Business listings and locations |
| `google_search_aio` | Google | AI Overview results |
### LLM Platforms
| Agent | Platform | Description |
| ------------ | ------------- | --------------------- |
| `chatgpt` | ChatGPT | Prompt responses |
| `perplexity` | Perplexity | Search + AI responses |
| `gemini` | Google Gemini | Prompt responses |
| `grok` | Grok | Prompt responses |
### Social Media
| Agent | Platform | Description |
| ---------------- | -------- | --------------------------- |
| `tiktok_account` | TikTok | Account profiles and videos |
| `facebook_page` | Facebook | Page information |
| `youtube_shorts` | YouTube | Short-form videos |
## Create Custom Agents
Can't find an agent for your target website? Create your own using **Agentic Studio** - no coding required.
Go to the [Agentic Studio](https://online.nimbleway.com/workflow-builder/create) in Nimble Platform
Enter the website URL and describe what data you need in plain English:
*"Extract product name, price, rating, and all review comments"*
Our AI analyzes the page and builds an extraction agent automatically - no CSS selectors needed
Preview extracted data and refine your description if needed
Your custom agent is available via the same Agent API with your chosen name
### Custom agent example
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Use your custom agent just like a public one
result = nimble.agent.run(
agent="my_custom_store_pdp", # Your custom agent name
params={
"url": "https://www.nike.com/t/air-max-90-mens-shoes"
}
)
parsed = result.data.parsing["parsed"]
print(f"Product: {parsed['product_name']}")
print(f"Price: ${parsed['price']}")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Use your custom agent just like a public one
const result = await nimble.agent.run({
agent: "my_custom_store_pdp", // Your custom agent name
params: {
url: "https://www.nike.com/t/air-max-90-mens-shoes",
},
});
const parsed = result.data.parsing.parsed;
console.log(`Product: ${parsed.product_name}`);
console.log(`Price: $${parsed.price}`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/agents/run' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"agent": "my_custom_store_pdp",
"params": {
"url": "https://www.nike.com/t/air-max-90-mens-shoes"
}
}'
```
**Custom agents are private to your account** and not maintained by Nimble.
You're responsible for updating them if the target site changes. For popular
sites, always prefer public agents which are **maintained by Nimble** 24/7.
## Response Fields
| Field | Type | Description |
| -------------- | ------ | --------------------------------- |
| `url` | string | The URL that was extracted |
| `task_id` | string | Unique identifier for the request |
| `status` | string | `success` or `failed` |
| `data.html` | string | Raw HTML content |
| `data.parsing` | object | Structured extracted data |
| `status_code` | number | HTTP status code from target |
## Use cases
Track prices across Amazon, Walmart, and other retailers with consistent
data formats
Gather comprehensive product data from major e-commerce platforms
Monitor Google, Bing, and marketplace search results for SEO and visibility
Extract competitor data from any website using public or custom agents
## Agents vs other tools
| What you need | Use |
| ---------------------------------------------- | ----------------------------------------------------------------------------------------- |
| Data from popular sites (Amazon, Google, etc.) | **Public Agents** - [browse gallery](/nimble-sdk/agentic/agent-gallery) |
| Data from sites not in the gallery | **Custom Agents** - [create in Studio](/nimble-sdk/agentic/studio) |
| Data from specific URLs (expert users) | [**Extract**](/nimble-sdk/web-tools/extract/quickstart) - full control with CSS selectors |
| Data from entire website | [**Crawl**](/nimble-sdk/web-tools/crawl) |
| Search web + extract content from results | [**Search**](/nimble-sdk/web-tools/search) |
**Most users should start with Web Search Agents.** Public agents cover
popular sites with zero configuration. For anything else, create a custom
agent in the Agentic Studio - it's the fastest path to production-ready data
extraction.
## Next steps
Browse all available public agents with API documentation
Explore endpoints, request parameters, and response schemas for the Agents
API
Create custom agents for any website with natural language
# Agent Creation
Source: https://docs.nimbleway.com/nimble-sdk/agentic/studio
Create custom Web Search Agents with natural language - no coding required
## Overview
**Agentic Studio** is a no-code tool for creating custom Web Search Agents. Simply describe what data you need in plain English, and our AI builds a production-ready agent for you. No CSS selectors, no coding, no scraping expertise required.
Think of it as having an expert scraper build your agent for you - just tell it what you want.
Open the Agentic Studio in Nimble Platform
Use the Nimble Agents skill to generate agents and write a full analysis script from a single prompt
## Why use Agentic Studio?
Describe what you need in natural language - the AI handles the technical
details
Agents are optimized for scale with predictable costs, unlike one-off Ask
calls
Create agents for sites not covered by our public gallery
Use your custom agent via the same Agent API immediately
## How it works
Go to the [Agentic
Studio](https://online.nimbleway.com/workflow-builder/create) in the Nimble
Platform
Enter the website URL you want to extract from and describe what data you
need in plain English. For example: "Extract product name, price, rating,
and all review comments"
Our AI analyzes the page structure and builds an extraction agent based on
your description. It identifies the right selectors and data patterns
automatically.
Preview the extracted data to make sure it matches your needs. Refine your
description if needed - the AI will adjust the agent.
Save your agent with a custom name. It's now available via the Agent API -
just like public Agent, but private to your account.
## Custom vs. Public Agent
| Feature | Public Agent | Custom Agent |
| ------------ | --------------------------------- | ------------------------- |
| Maintenance | **Maintained by Nimble** 24/7 | Maintained by you |
| Setup | Zero - just use agent name | Create in Agentic Studio |
| Availability | Popular sites | Any website |
| Auto-healing | Yes - we update when sites change | No - you update if needed |
| API usage | Same Agent API | Same Agent API |
| Visibility | Available to all users | Private to your account |
**Always prefer public Agent when available.** They're battle-tested,
auto-healing, and **maintained by Nimble**. Only create custom Agent for sites
not in the gallery.
## Example: Creating a custom agent
Let's say you need to extract data from a niche e-commerce site that's not in our public gallery.
**Step 1: Enter the URL**
```
https://example-niche-store.com/products/widget-pro
```
**Step 2: Describe what you need**
```
Extract the product name, current price, original price (if on sale),
stock status, all product specifications as key-value pairs,
and the first 5 customer reviews with rating and text.
```
**Step 3: Review the extracted data**
```json theme={"system"}
{
"product_name": "Widget Pro 3000",
"current_price": 49.99,
"original_price": 79.99,
"stock_status": "In Stock",
"specifications": [
{ "key": "Dimensions", "value": "10 x 5 x 3 inches" },
{ "key": "Weight", "value": "1.2 lbs" },
{ "key": "Material", "value": "Aluminum" }
],
"reviews": [
{ "rating": 5, "text": "Excellent product, exactly what I needed!" },
{ "rating": 4, "text": "Good quality, fast shipping." }
]
}
```
**`Step 4: Save as niche_store_pdp`**
**Step 5: Use via API**
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Use your custom agent just like a public one
result = nimble.agent.run(
agent="niche_store_pdp", # Your custom agent name
params={
"url": "https://example-niche-store.com/products/another-widget"
}
)
print(f"Product: {result['parsing']['parsed']['product_name']}")
print(f"Price: ${result['parsing']['parsed']['current_price']}")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Use your custom agent just like a public one
const result = await nimble.agent.run({
agent: "niche_store_pdp", // Your custom agent name
params: {
url: "https://example-niche-store.com/products/another-widget",
},
});
console.log(`Product: ${result.parsing.parsed.product_name}`);
console.log(`Price: $${result.parsing.parsed.current_price}`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/agents/run' \
--header 'Authorization: Bearer YOUR-API-KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"agent": "niche_store_pdp",
"params": {
"url": "https://example-niche-store.com/products/another-widget"
}
}'
```
## Tips for better agents
**Be specific about data types** Instead of "get the price", say "extract the current price as a number without currency symbols"
**Describe the structure you want** Instead of "get reviews", say "extract reviews as an array with rating (1-5) and review text for each"
**Mention edge cases** "Extract the sale price if available, otherwise use the regular price"
**Test with multiple pages** Try your agent on different product pages to ensure it works consistently
### Agent naming
* Use lowercase with underscores: `my_store_pdp`
* Be descriptive: `competitor_pricing` not `agent1`
* Include the site or type: `niche_store_reviews`
## Limitations
* **Maintenance is your responsibility**: Unlike public Agent that are **maintained by Nimble**, you need to update custom Agent if the target site changes its structure
* **Single-page extraction**: Agents extract from one page type. For multi-page workflows, create separate agents
## FAQ
Yes! Custom Agent are designed for production use. They use the same
reliable infrastructure as public Agent with predictable costs and high
throughput.
Unlike public Agent (**maintained by Nimble** 24/7), custom Agent don't
auto-heal. If your extractions start failing or returning incorrect data,
you'll need to update your agent in the Agentic Studio.
There's no limit on the number of custom Agent you can create. Create as
many as you need for your use cases.
Yes, custom Agent are available to all members of your Nimble account.
They're private to your organization but shared within your team.
## Next steps
Start creating your first custom agent
Check if a public agent exists for your site first
Learn how to use Web Search Agents via API
# Installation
Source: https://docs.nimbleway.com/nimble-sdk/getting-started/installation
Get started with Nimble by installing our SDK or CLI and setting up your environment
**Using the API directly?** If you prefer HTTP requests (cURL, fetch, axios,
etc.) you can skip installation and go straight to the [API
Reference](/api-reference/introduction).
## Prerequisites
* A valid [Nimble API key](https://online.nimbleway.com/account-settings/api-keys)
* One of the following runtimes for your chosen SDK:
* **Python**: 3.9+
* **Node.js**: 20 LTS+
* **Go**: 1.22+
## Python
```bash httpx theme={"system"}
pip install nimble_python
```
```bash aiohttp theme={"system"}
pip install "nimble_python[aiohttp]"
```
[View Python SDK docs →](/nimble-sdk/sdks/python)
## Node.js
```bash theme={"system"}
npm install @nimble-way/nimble-js
```
Works with Node.js 20+, Deno v1.28+, Bun 1.0+, and Cloudflare Workers.
[View Node SDK docs →](/nimble-sdk/sdks/node)
## Go
```bash theme={"system"}
go get github.com/Nimbleway/nimble-go@latest'
```
[View Go SDK docs →](/nimble-sdk/sdks/go)
## CLI
The Nimble CLI lets you interact with the API directly from your terminal (requires Go 1.22+):
```bash theme={"system"}
go install 'github.com/Nimbleway/nimble-cli/cmd/nimble@latest'
```
Add the Go bin directory to your PATH if needed:
```bash theme={"system"}
export PATH="$PATH:$(go env GOPATH)/bin"
```
[View CLI docs →](/nimble-sdk/sdks/cli)
## Authentication
All SDKs and the CLI read your API key from the `NIMBLE_API_KEY` environment variable:
```bash macOS / Linux theme={"system"}
export NIMBLE_API_KEY="your-api-key"
```
```bash Windows (PowerShell) theme={"system"}
$env:NIMBLE_API_KEY="your-api-key"
```
You can also pass it directly when initializing the client (not recommended for production):
```python Python theme={"system"}
from nimble_python import Nimble
client = Nimble(api_key="your-api-key")
```
```typescript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "your-api-key" });
```
```go Go theme={"system"}
import (
nimble "github.com/Nimbleway/nimble-go"
"github.com/Nimbleway/nimble-go/option"
)
client := nimble.NewClient(option.WithAPIKey("your-api-key"))
```
## Next Steps
Make your first request in minutes
Sync and async Python client
TypeScript/JavaScript client
Idiomatic Go client
Use Nimble from your terminal
Full REST API documentation
# Welcome to Nimble
Source: https://docs.nimbleway.com/nimble-sdk/getting-started/overview
The AI-Native SDK for Real-Time Web Data at scale
## Get Started
Nimble provides enterprise-grade web data infrastructure designed for developers who need reliable access to web content at scale. Whether you're building data pipelines, conducting market research, or powering AI applications, our platform delivers the tools and infrastructure to access web data without the complexity of managing proxies, browsers, or stealth technology.
Start using Nimble's web data platform in minutes:
Sign up and get your API credentials to start building
Test & Explore the API effortleslly, no code is needed
Quick start guides with code examples, learn how to use nimble in minutes.
## Nimble Products
Nimble's products are built as layers of abstraction, each leveraging the infrastructure below it. Start with raw proxy access for maximum control, use the Web API for browser automation, or leverage AI agents for intelligent data retrieval. Choose the layer that best fits your use case.
Pre-built extraction agents for popular platforms - zero configuration
required
Plug-and-play skills for Claude Code, Cursor, and other AI coding assistants
High-performance residential proxy network with advanced stealth
capabilities \
([Contact](https://login.start-chat.com/modal/601e4da4-50a0-4dc7-8155-bb84f2952c40/27847549-dc04-4144-98a5-d40e568bf6af?magicLinkId=slFQ2j\&UID=65ab324c-ecde-4748-9f52-8e395054774b.1753267174019)
sales to gain access)
Browser automation and data extraction API for raw & dynamic content
# Quickstart Guide
Source: https://docs.nimbleway.com/nimble-sdk/getting-started/quickstart
This guide will help you make your first request with Nimble in just a few minutes.
First, create your nimble account at [Nimble Sign Up](https://online.nimbleway.com/signup).
Already have an account? Just login to [Nimble dashboard](https://online.nimbleway.com/signup).
Now, obtain your API key from the [Account Settings](https://online.nimbleway.com/account-settings/api-keys).
Install the Nimble SDK in your preferred language:
```bash Python theme={"system"}
pip install nimble_python
```
```bash Node theme={"system"}
npm install @nimble-way/sdk
```
**Prefer using the API directly?** Skip the SDK installation and use HTTP requests (see cURL examples below) or visit the [API Reference](/api-reference/introduction) for complete endpoint documentation.
**Extract**
Get clean HTML and structured data from any URL:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url= "https://www.example.com",
render= True
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://www.example.com",
render: true
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true
}'
```
**Web Search Agents**
Use pre-built templates for popular platforms:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.agent.run(
agent= "amazon_pdp",
params= {
"asin": "B08N5WRWNW"
}
)
print(result)
```
```typescript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.agent.run({
agent: "amazon_pdp",
params: {
asin: "B08N5WRWNW"
}
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/agents/run' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"agent": "amazon_pdp",
"params": {
"asin": "B08N5WRWNW"
}
}'
```
**Search**
Perform web searches and get structured results:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.search(
query= "data scraping tools",
country= "US"
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.search({
query: "data scraping tools",
country: "US"
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/search' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"query": "data scraping tools",
"country": "US"
}'
```
**Map**
Fast URL discovery and site structure mapping:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.map(
URL= "https://www.example.com",
sitemap= "only"
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.map({
URL: "https://www.example.com",
sitemap: "only"
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/map' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"URL": "https://www.example.com",
"sitemap": "only"
}'
```
**Crawl**
Discover and map entire websites automatically:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.crawl.run(
url= "https://www.example.com",
limit= 100
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.crawl.run({
url: "https://www.example.com",
limit: 100
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/crawl' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"limit": 100
}'
```
**Ready to build something real?**
End-to-end tutorial: use the Nimble Agents skill to build a competitive analysis script for shoes across Amazon, Walmart, and Nike
Explore the **Web Tools** documentation:
Get clean & structured data from any URL
Ready-to-use extraction templates for popular platforms
Perform web searches and retrieve parsed content from top results
Fast URL discovery and site structure mapping
Map and Extract content from entire websites at scale
Access premium residential IPs with Nimble's Proxy Infrastructure ([Contact](https://portal.usepylon.com/nimble) sales to gain access)
Use the **API** directly, bring Nimble into your **AI coding assistant**, or connect via **MCP**:
Full API documentation
Plug-and-play skills for Claude Code, Cursor, and other AI coding assistants
Connect AI agents and 3rd party tools to Nimble's web data infrastructure
Install an **SDK** and start building in your language of choice:
`nimble_python`
`@nimbleway/sdk`
`nimble-go`
`nimble-cli`
Manage your **account**, review **pricing**, and monitor **service health**:
Manage API keys and collaborate with your team
Usage-based pricing for all Nimble APIs and Data Services plans
Real-time status of all Nimble services
# CLI
Source: https://docs.nimbleway.com/nimble-sdk/sdks/cli
Official Nimble CLI — interact with the Nimble API directly from your terminal
The Nimble CLI lets you run extractions, searches, crawls, and agents directly from your terminal — no code required.
## Installation
The CLI requires **Go 1.22+**.
```bash theme={"system"}
go install 'github.com/Nimbleway/nimble-cli/cmd/nimble@latest'
```
The binary installs to `$HOME/go/bin`. Add it to your `PATH` if needed:
```bash theme={"system"}
export PATH="$PATH:$(go env GOPATH)/bin"
```
Verify the installation:
```bash theme={"system"}
nimble --version
```
## Authentication
Set your API key as an environment variable:
```bash theme={"system"}
export NIMBLE_API_KEY="your-api-key"
```
Get your API key from [Account Settings](https://online.nimbleway.com/account-settings/api-keys).
## Command Structure
All commands follow a resource-based pattern:
```bash theme={"system"}
nimble [resource] [flags...]
```
Run `nimble --help` to list all resources, or `nimble [resource] --help` for resource-specific usage.
## Core Commands
### Extract
Extract clean content from any URL:
```bash theme={"system"}
nimble extract --url "https://www.example.com"
```
With JavaScript rendering and geo-targeting:
```bash theme={"system"}
nimble extract \
--url "https://www.example.com" \
--render true \
--country US
```
### Search
Perform a real-time web search:
```bash theme={"system"}
nimble search --query "best web scraping tools" --country US
```
### Map
Discover all URLs in a domain:
```bash theme={"system"}
nimble map --url "https://www.example.com" --sitemap only
```
### Crawl
Crawl an entire website:
```bash theme={"system"}
nimble crawl run --url "https://www.example.com" --limit 100
```
### Agents
Run a pre-built agent:
```bash theme={"system"}
nimble agent run --agent amazon_pdp --params '{"asin": "B08N5WRWNW"}'
```
## Output Formats
Control response formatting with the `--format` flag:
| Format | Description |
| --------- | -------------------------------- |
| `auto` | Automatic (default) |
| `pretty` | Pretty-printed JSON |
| `json` | Compact JSON |
| `jsonl` | JSON Lines (one object per line) |
| `yaml` | YAML output |
| `raw` | Raw API response body |
| `explore` | Interactive explorer view |
```bash theme={"system"}
nimble extract --url "https://www.example.com" --format pretty
```
## Transforming Output
Use `--transform` with [GJSON syntax](https://github.com/tidwall/gjson) to extract specific fields:
```bash theme={"system"}
# Extract just the task_id
nimble extract --url "https://www.example.com" --transform "task_id"
# Extract a nested field
nimble extract --url "https://www.example.com" --transform "data.html"
```
## File Arguments
Pass file contents as argument values using `@filename` syntax:
```bash theme={"system"}
# Pass a JSON schema file
nimble extract --url "https://www.example.com" --parsing-schema @schema.json
# Pass a file inside a JSON structure
nimble extract --options '{"parsing_schema": "@schema.json"}'
```
Use `@file://filename` for plain text or `@data://filename` for base64-encoded content.
## Global Flags
| Flag | Description |
| ------------------- | ------------------------------------------- |
| `--help` | Show help for any command |
| `--debug` | Enable debug logging with full HTTP details |
| `--version`, `-v` | Display the CLI version |
| `--base-url` | Override the API base URL |
| `--format` | Set output format |
| `--format-error` | Set error output format |
| `--transform` | Transform output using GJSON syntax |
| `--transform-error` | Transform error output using GJSON syntax |
## Debug Mode
Enable `--debug` to inspect the full HTTP request and response — useful for troubleshooting:
```bash theme={"system"}
nimble extract --url "https://www.example.com" --debug
```
## Next Steps
Full REST API documentation for all endpoints
Extract features and parameters
Real-time web search with structured results
Pre-built extraction agents for popular platforms
# Go
Source: https://docs.nimbleway.com/nimble-sdk/sdks/go
Official Nimble SDK for Go — type-safe client for web extraction, search, crawl, map, and agents
Install the Nimble Go library to interact with the Nimble API from your Go applications. Built with idiomatic Go patterns, full context support, and automatic retries.
## Installation
```sh theme={"system"}
go get github.com/Nimbleway/nimble-go@latest'
```
Requires **Go 1.22+**. Set your API key via the `NIMBLE_API_KEY` environment
variable or pass it directly using `option.WithAPIKey()`.
## Setup
Import the package and initialize the client:
```go Go theme={"system"}
package main
import (
"context"
"fmt"
"os"
nimble "github.com/Nimbleway/nimble-go"
"github.com/Nimbleway/nimble-go/option"
)
func main() {
client := nimble.NewClient(
option.WithAPIKey(os.Getenv("NIMBLE_API_KEY")),
)
_ = client
fmt.Println("Client ready")
}
```
## Quick Start
Extract content from a URL:
```go Go theme={"system"}
package main
import (
"context"
"fmt"
"os"
nimble "github.com/Nimbleway/nimble-go"
"github.com/Nimbleway/nimble-go/option"
)
func main() {
client := nimble.NewClient(
option.WithAPIKey(os.Getenv("NIMBLE_API_KEY")),
)
result, err := client.Extract(context.TODO(), nimble.ExtractParams{
URL: "https://www.example.com",
})
if err != nil {
panic(err)
}
fmt.Printf("Task ID: %s\n", result.TaskID)
}
```
## Core Methods
### Extract
Get clean HTML, markdown, or structured data from any URL:
```go Go theme={"system"}
result, err := client.Extract(context.TODO(), nimble.ExtractParams{
URL: "https://www.example.com",
Render: nimble.Bool(true),
})
if err != nil {
panic(err)
}
fmt.Println(result.TaskID)
```
Optional fields are wrapped in `param.Opt[T]`. Use the provided constructors —
`nimble.Bool()`, `nimble.String()`, `nimble.Int()` — to set them.
### Search
Perform real-time web searches:
```go Go theme={"system"}
result, err := client.Search(context.TODO(), nimble.SearchParams{
Query: "best web scraping tools",
Country: nimble.String("US"),
})
if err != nil {
panic(err)
}
fmt.Println(result)
```
### Map
Discover all URLs within a domain or sitemap:
```go Go theme={"system"}
result, err := client.Map(context.TODO(), nimble.MapParams{
URL: "https://www.example.com",
Sitemap: nimble.String("only"),
})
if err != nil {
panic(err)
}
fmt.Println(result)
```
### Crawl
Recursively crawl and extract an entire website:
```go Go theme={"system"}
result, err := client.Crawl.Run(context.TODO(), nimble.CrawlRunParams{
URL: "https://www.example.com",
Limit: nimble.Int(100),
})
if err != nil {
panic(err)
}
fmt.Println(result)
```
### Agents
Run pre-built agents for structured data from popular platforms:
```go Go theme={"system"}
result, err := client.Agent.Run(context.TODO(), nimble.AgentRunParams{
Agent: "amazon_pdp",
Params: map[string]interface{}{
"asin": "B08N5WRWNW",
},
})
if err != nil {
panic(err)
}
fmt.Println(result)
```
Browse the full agent catalog in the [Agent
Gallery](/nimble-sdk/agentic/agent-gallery).
## Error Handling
Check `err != nil` for any failed request. Use `errors.As` to inspect typed API errors:
```go Go theme={"system"}
import (
"errors"
"fmt"
nimble "github.com/Nimbleway/nimble-go"
)
result, err := client.Extract(context.TODO(), nimble.ExtractParams{
URL: "https://www.example.com",
})
if err != nil {
var apiErr *nimble.Error
if errors.As(err, &apiErr) {
fmt.Printf("API error — status: %d, message: %s\n",
apiErr.StatusCode, apiErr.Message)
}
panic(err)
}
```
The `*nimble.Error` type exposes:
* `StatusCode int` — HTTP status code
* `Message string` — Human-readable error description
## Configuration
### Retries
The SDK retries automatically on connection errors, timeouts, and server failures (2 retries by default):
```go Go theme={"system"}
// Configure globally
client := nimble.NewClient(
option.WithAPIKey(os.Getenv("NIMBLE_API_KEY")),
option.WithMaxRetries(3),
)
// Disable retries for a specific request
result, err := client.Extract(context.TODO(), nimble.ExtractParams{
URL: "https://www.example.com",
}, option.WithMaxRetries(0))
```
### Timeouts
Use Go's standard `context` package for request timeouts:
```go Go theme={"system"}
import (
"context"
"time"
)
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
result, err := client.Extract(ctx, nimble.ExtractParams{
URL: "https://www.example.com",
})
```
Or set a per-request timeout directly:
```go Go theme={"system"}
result, err := client.Extract(context.TODO(), nimble.ExtractParams{
URL: "https://www.example.com",
}, option.WithRequestTimeout(30*time.Second))
```
## Advanced
### Raw Response Access
Capture the raw HTTP response alongside the parsed result:
```go Go theme={"system"}
import "net/http"
var rawResponse *http.Response
result, err := client.Extract(context.TODO(), nimble.ExtractParams{
URL: "https://www.example.com",
}, option.WithResponseInto(&rawResponse))
if err != nil {
panic(err)
}
fmt.Println(rawResponse.Header.Get("x-request-id"))
fmt.Println(result.TaskID)
```
### Custom Request Options
Attach additional headers or query parameters to any request:
```go Go theme={"system"}
result, err := client.Extract(context.TODO(), nimble.ExtractParams{
URL: "https://www.example.com",
},
option.WithHeader("X-Custom-Header", "value"),
option.WithQueryParam("debug", "true"),
)
```
## Next Steps
Full REST API documentation for all endpoints
Rendering, formats, stealth mode, and more
Real-time web search with structured results
Pre-built extraction agents for popular platforms
# Node
Source: https://docs.nimbleway.com/nimble-sdk/sdks/node
Official Nimble SDK for Node.js and TypeScript — async client for web extraction, search, crawl, map, and agents
Install the Nimble JavaScript/TypeScript library to interact with the Nimble API from Node.js, Deno, Bun, Cloudflare Workers, and modern browsers. All methods are async and return typed responses.
## Installation
```bash theme={"system"}
npm install @nimble-way/sdk
```
Requires **Node.js 20 LTS+** (also supports Deno v1.28+, Bun 1.0+, and
Cloudflare Workers). Never hardcode your API key — use environment variables.
## Setup
Initialize the client with your API key:
```typescript TypeScript theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({
apiKey: process.env.NIMBLE_API_KEY,
});
```
## Quick Start
Extract content from a URL in one call:
```typescript TypeScript theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: process.env.NIMBLE_API_KEY });
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
});
console.log(result.task_id);
```
## TypeScript Types
The SDK ships full TypeScript definitions for all request parameters and responses, with IDE autocompletion:
```typescript TypeScript theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: process.env.NIMBLE_API_KEY });
const params: Nimble.ExtractParams = {
url: "https://www.example.com",
render: true,
};
const result: Nimble.ExtractResponse = await nimble.extract(params);
console.log(result.task_id);
```
## Core Methods
### Extract
Get clean HTML, markdown, or structured data from any URL. Supports JavaScript rendering, stealth mode, browser actions, and more.
```typescript TypeScript theme={"system"}
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
});
console.log(result.task_id);
```
See the [Extract docs](/nimble-sdk/web-tools/extract/quickstart) for the full
parameter list — geo-targeting, output formats, parsing schemas, and more.
### Search
Perform real-time web searches and get structured results:
```typescript TypeScript theme={"system"}
const result = await nimble.search({
query: "best web scraping tools",
country: "US",
});
console.log(result);
```
### Map
Discover all URLs within a domain or sitemap:
```typescript TypeScript theme={"system"}
const result = await nimble.map({
URL: "https://www.example.com",
sitemap: "only",
});
console.log(result);
```
### Crawl
Recursively crawl and extract an entire website at scale:
```typescript TypeScript theme={"system"}
const result = await nimble.crawl.run({
url: "https://www.example.com",
limit: 100,
});
console.log(result);
```
### Agents
Run pre-built agents for structured data from popular platforms:
```typescript TypeScript theme={"system"}
const result = await nimble.agent.run({
agent: "amazon_pdp",
params: {
asin: "B08N5WRWNW",
},
});
console.log(result);
```
Browse the full agent catalog in the [Agent
Gallery](/nimble-sdk/agentic/agent-gallery).
## Error Handling
The SDK throws typed `APIError` subclasses for failed requests:
```typescript TypeScript theme={"system"}
import Nimble, { APIError } from "nimble-js";
const nimble = new Nimble({ apiKey: process.env.NIMBLE_API_KEY });
try {
const result = await nimble.extract({ url: "https://www.example.com" });
} catch (error) {
if (error instanceof APIError) {
console.log(`Status: ${error.status}`);
console.log(`Message: ${error.message}`);
}
throw error;
}
```
| Error Class | HTTP Status | When it occurs |
| ----------------------- | ----------- | -------------------------------- |
| `BadRequestError` | 400 | Invalid request parameters |
| `AuthenticationError` | 401 | Invalid or missing API key |
| `PermissionDeniedError` | 403 | Insufficient account permissions |
| `NotFoundError` | 404 | Resource not found |
| `RateLimitError` | 429 | Request rate exceeded |
| `InternalServerError` | 500+ | Server-side error |
## Configuration
### Timeouts & Retries
The SDK retries automatically on connection errors and server failures. Defaults: **2 retries**, **3-minute timeout**.
```typescript TypeScript theme={"system"}
// Configure globally
const nimble = new Nimble({
apiKey: process.env.NIMBLE_API_KEY,
maxRetries: 3,
timeout: 60 * 1000, // 60 seconds in ms
});
// Override per-request
const result = await nimble.extract(
{ url: "https://www.example.com" },
{ maxRetries: 0 },
);
```
### Logging
Control log verbosity via environment variable:
```bash theme={"system"}
export NIMBLE_LOG=debug
```
Or configure programmatically using any compatible logger (pino, winston, consola, etc.):
```typescript TypeScript theme={"system"}
import Nimble from "@nimble-way/nimble-js";
import pino from "pino";
const nimble = new Nimble({
apiKey: process.env.NIMBLE_API_KEY,
logger: pino(),
logLevel: "debug",
});
```
## Advanced
### Raw Response Access
Access HTTP headers and status alongside the parsed response:
```typescript TypeScript theme={"system"}
// Get just the raw Response object
const raw = await nimble
.extract({ url: "https://www.example.com" })
.asResponse();
console.log(raw.headers.get("x-request-id"));
// Get both parsed result and raw response
const { data, response } = await nimble
.extract({ url: "https://www.example.com" })
.withResponse();
console.log(response.headers.get("x-request-id"));
console.log(data.task_id);
```
### Custom Fetch / Proxy
Provide a custom fetch implementation or configure proxies for Node.js, Bun, and Deno:
```typescript TypeScript theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({
apiKey: process.env.NIMBLE_API_KEY,
fetchOptions: {
proxy: "http://proxy.example.com:8080",
},
});
```
### MCP Server
The SDK includes a built-in [MCP Server](https://modelcontextprotocol.io) for AI assistant integrations, enabling API exploration and request testing directly from tools like Claude.
## Next Steps
Full REST API documentation for all endpoints
Rendering, formats, stealth mode, and more
Real-time web search with structured results
Pre-built extraction agents for popular platforms
# Python
Source: https://docs.nimbleway.com/nimble-sdk/sdks/python
Official Nimble Python SDK — sync and async client for web extraction, search, crawl, map, and agents
Install the Nimble Python library to interact with the Nimble API from your Python applications. Supports both synchronous and asynchronous usage with full type hints.
## Installation
```bash pip theme={"system"}
pip install nimble_python
```
```bash pip (async HTTP backend) theme={"system"}
pip install "nimble_python[aiohttp]"
```
Requires **Python 3.9+**. Never hardcode your API key — use environment
variables instead.
## Setup
Initialize the client with your API key. We recommend loading it from the environment:
```python Python theme={"system"}
import os
from nimble_python import Nimble
client = Nimble(api_key=os.environ.get("NIMBLE_API_KEY"))
```
## Quick Start
Extract clean content from a URL in one call:
```python Python theme={"system"}
import os
from nimble_python import Nimble
client = Nimble(api_key=os.environ.get("NIMBLE_API_KEY"))
result = client.extract(url="https://www.example.com", render=True)
print(result.task_id)
```
## Core Methods
### Extract
Get clean HTML, markdown, or structured data from any URL. Supports JavaScript rendering, stealth mode, browser actions, and more.
```python Python theme={"system"}
result = client.extract(
url="https://www.example.com",
render=True
)
print(result.task_id)
```
See the [Extract docs](/nimble-sdk/web-tools/extract/quickstart) for the full
parameter list — geo-targeting, output formats, parsing schemas, and more.
### Search
Perform real-time web searches and get structured results:
```python Python theme={"system"}
result = client.search(
query="best web scraping tools",
country="US"
)
print(result)
```
### Map
Discover all URLs within a domain or sitemap:
```python Python theme={"system"}
result = client.map(
URL="https://www.example.com",
sitemap="only"
)
print(result)
```
### Crawl
Recursively crawl and extract an entire website at scale:
```python Python theme={"system"}
result = client.crawl.run(
url="https://www.example.com",
limit=100
)
print(result)
```
### Agents
Run pre-built agents for structured data from popular platforms:
```python Python theme={"system"}
result = client.agent.run(
agent="amazon_pdp",
params={"asin": "B08N5WRWNW"}
)
print(result)
```
Browse the full agent catalog in the [Agent
Gallery](/nimble-sdk/agentic/agent-gallery).
## Async Client
Use `AsyncNimble` for non-blocking, concurrent operations:
```python Python theme={"system"}
import asyncio
import os
from nimble_python import AsyncNimble
client = AsyncNimble(api_key=os.environ.get("NIMBLE_API_KEY"))
async def main():
result = await client.extract(url="https://www.example.com", render=True)
print(result.task_id)
asyncio.run(main())
```
### aiohttp Backend
For high-concurrency workloads, use the `aiohttp` HTTP backend (requires `pip install "nimble_python[aiohttp]"`):
```python Python theme={"system"}
import asyncio
import os
from nimble_python import AsyncNimble, DefaultAioHttpClient
async def main():
async with AsyncNimble(
api_key=os.environ.get("NIMBLE_API_KEY"),
http_client=DefaultAioHttpClient(),
) as client:
result = await client.extract(url="https://www.example.com", render=True)
print(result.task_id)
asyncio.run(main())
```
Always use `async with` when working with `DefaultAioHttpClient` to ensure
proper resource cleanup.
## Error Handling
The SDK maps API failures to typed exception classes:
```python Python theme={"system"}
import nimble_python
import os
from nimble_python import Nimble
client = Nimble(api_key=os.environ.get("NIMBLE_API_KEY"))
try:
result = client.extract(url="https://www.example.com")
except nimble_python.APIConnectionError as e:
print("Connection failed:", e)
except nimble_python.AuthenticationError as e:
print("Invalid API key — check NIMBLE_API_KEY")
except nimble_python.RateLimitError as e:
print("Rate limited — back off and retry:", e)
except nimble_python.APIStatusError as e:
print(f"API error {e.status_code}:", e.message)
```
| Exception | HTTP Status | When it occurs |
| ----------------------- | ----------- | -------------------------------- |
| `APIConnectionError` | — | Network failure or timeout |
| `AuthenticationError` | 401 | Invalid or missing API key |
| `PermissionDeniedError` | 403 | Insufficient account permissions |
| `RateLimitError` | 429 | Request rate exceeded |
| `InternalServerError` | 500+ | Server-side error |
## Configuration
### Timeouts & Retries
The SDK retries automatically on connection errors and server failures. Defaults: **2 retries**, **3-minute timeout**.
```python Python theme={"system"}
import os
from nimble_python import Nimble
# Configure globally
client = Nimble(
api_key=os.environ.get("NIMBLE_API_KEY"),
max_retries=3,
timeout=60.0, # seconds
)
# Override per-request
result = client.with_options(max_retries=0).extract(
url="https://www.example.com"
)
```
### Logging
Enable SDK-level debug logging via environment variable:
```bash theme={"system"}
export NIMBLE_LOG=debug
```
Or configure programmatically:
```python Python theme={"system"}
import logging
logging.basicConfig()
logging.getLogger("nimble_python").setLevel(logging.DEBUG)
```
## Advanced
### Raw Response Access
Access HTTP headers and response metadata alongside the parsed result:
```python Python theme={"system"}
response = client.with_raw_response.extract(url="https://www.example.com")
print(response.headers.get("x-request-id"))
result = response.parse()
print(result.task_id)
```
### Streaming Response
Stream large response bodies instead of buffering them in memory:
```python Python theme={"system"}
with client.with_streaming_response.extract(url="https://www.example.com") as response:
for chunk in response.iter_bytes():
process(chunk)
```
## Next Steps
Full REST API documentation for all endpoints
Rendering, formats, stealth mode, and more
Real-time web search with structured results
Pre-built extraction agents for popular platforms
# Agent Skills
Source: https://docs.nimbleway.com/nimble-sdk/sdks/skills
Nimble agent skills for Claude Code, Cursor, and Vercel — bring real-time web data into your AI workflows
## Prerequisites
**1. Nimble CLI** — Required by the `nimble-web-tools` skill:
```bash theme={"system"}
npm install -g @nimble-way/nimble-cli
```
**2. Nimble API Key** — Get yours from [Account Settings](https://online.nimbleway.com/account-settings/api-keys) and set it as an environment variable:
```bash theme={"system"}
export NIMBLE_API_KEY="your-api-key"
```
Or persist it in `~/.claude/settings.json` for Claude Code:
```json theme={"system"}
{
"env": {
"NIMBLE_API_KEY": "your-api-key"
}
}
```
## Installation
Install from the Nimble Marketplace — this adds both skills and configures the MCP server automatically:
```bash theme={"system"}
claude plugin marketplace add Nimbleway/agent-skills &&
claude plugin install nimble@nimble-plugin-marketplace
```
Or load directly from a local clone:
```bash theme={"system"}
git clone https://github.com/Nimbleway/agent-skills.git &&
claude --plugin-dir /path/to/agent-skills
```
**Step 1:** Add the Nimble MCP server to Cursor:
Replace `NIMBLE_API_KEY` in **Cursor Settings > MCP Servers** with your actual key.
**Step 2:** Install skills and rules:
```bash theme={"system"}
npx skills add Nimbleway/agent-skills -a cursor
```
```bash theme={"system"}
npx skills add Nimbleway/agent-skills
```
The `nimble-agents` skill requires the MCP server. Connect it manually after installing:
```bash theme={"system"}
claude mcp add --transport http nimble-mcp-server https://mcp.nimbleway.com/mcp \
--header "Authorization: Bearer ${NIMBLE_API_KEY}"
```
***
## What's Included
Agent Skills are plug-and-play extensions that give AI coding assistants direct access to Nimble's web data tools. Install once and your AI can search the live web, extract pages, map sites, and run structured data agents — automatically, from natural language.
| Skill | Description |
| -------------------- | ------------------------------------------------------------------------------- |
| **nimble-web-tools** | Real-time web intelligence — search, extract, map, and crawl via the Nimble CLI |
| **nimble-agents** | Find, generate, and run agents to extract structured data from any website |
| **MCP Server** | Pre-configured Nimble MCP server connection for agent-to-API access |
## nimble-web-tools Skill
The `nimble-web-tools` skill activates automatically when you ask your AI assistant to search the web, extract a page, map a site, or crawl for content.
### What it can do
| Tool | What it does |
| ----------- | --------------------------------------------------------------------------------------------------------- |
| **Search** | Real-time web search with 8 focus modes: general, coding, news, academic, shopping, social, geo, location |
| **Extract** | Get clean HTML or markdown from any URL — supports JS rendering and stealth unblocking |
| **Map** | Discover all URLs in a domain or sitemap — useful for planning extraction workflows |
| **Crawl** | Extract content from an entire website in one request |
### Example prompts
```
"Search for recent AI developments"
→ nimble search --query "recent AI developments" --deep-search=false
"Extract the content from this URL"
→ nimble extract --url "https://example.com" --parse --format markdown
"Map all pages on this docs site"
→ nimble map --url "https://docs.example.com" --limit 100
"Crawl the API reference section"
→ nimble crawl run --url "https://docs.example.com/api" --limit 50
```
### Search
```bash theme={"system"}
# Fast search (always use --deep-search=false for speed)
nimble search --query "React hooks tutorial" --topic coding --deep-search=false
# Search with AI-generated answer
nimble search --query "what is WebAssembly" --include-answer --deep-search=false
# News with time filter
nimble search --query "AI developments" --topic news --time-range week --deep-search=false
# Filter to specific domains
nimble search --query "auth best practices" \
--include-domain github.com \
--include-domain stackoverflow.com \
--deep-search=false
```
Use `--deep-search=false` for fast responses (1–3s). The default deep mode
fetches full page content and is 5–10× slower — only needed for full-text
archiving.
### Extract
```bash theme={"system"}
# Standard extraction — always pass --parse --format markdown for LLM-readable output
nimble extract --url "https://example.com/article" --parse --format markdown
# With JavaScript rendering (for SPAs and dynamic pages)
nimble extract --url "https://example.com/app" --render --parse --format markdown
# With geo-targeting
nimble extract --url "https://example.com" --country US --city "New York" --parse --format markdown
```
### Map
```bash theme={"system"}
# Discover all URLs on a site
nimble map --url "https://docs.example.com" --limit 100
# Include subdomains
nimble map --url "https://example.com" --domain-filter subdomains
```
### Crawl
```bash theme={"system"}
# Crawl a site (always set --limit)
nimble crawl run --url "https://docs.example.com" --limit 50
# Filter to specific paths
nimble crawl run --url "https://example.com" \
--include-path "/docs" \
--include-path "/api" \
--limit 100
# Check crawl status
nimble crawl status --id "crawl-id"
```
For LLM-friendly output, prefer `map` + `extract --parse --format markdown` on
individual pages rather than crawl — crawl returns raw HTML which can be very
large.
***
## nimble-agents Skill
The `nimble-agents` skill gives your AI assistant access to Nimble's pre-built agent library. It uses a find-or-generate workflow: search for an existing agent, run it, and get structured data. If no agent fits, generate a custom one via natural language.
### How it works
Find an existing agent matching your target website using
`nimble_agents_list`
Review the agent's input/output schema with `nimble_agents_get`
Execute the agent and get clean, structured results via `nimble_agents_run`
If no existing agent fits, create a custom one with `nimble_agents_generate`
Save generated agents for future reuse with `nimble_agents_publish`
### Usage
Use the slash command:
```
/nimble:nimble-agents extract product details from this Amazon page: https://www.amazon.com/dp/B0DGHRT7PS
```
Or just describe what you need in plain language — the skill activates automatically when relevant.
Reference the skill in Cursor Agent chat:
```
/nimble-agents extract product details from this Amazon page: https://www.amazon.com/dp/B0DGHRT7PS
```
### MCP Tools
| Tool | Purpose |
| ------------------------ | ------------------------------------------- |
| `nimble_agents_list` | Browse agents by keyword |
| `nimble_agents_get` | Get agent details and input/output schema |
| `nimble_agents_generate` | Create a custom agent via natural language |
| `nimble_agents_run` | Execute an agent and get structured results |
| `nimble_agents_publish` | Save a generated agent for reuse |
***
## Source Code
Plugin source, skill definitions, and SKILL.md references
Detailed platform-specific installation guide
Full command reference for nimble-web-tools
Full guide for the nimble-agents skill
# Crawl
Source: https://docs.nimbleway.com/nimble-sdk/web-tools/crawl
Extract structured data from entire websites automatically
Nimble **Crawl** (async) systematically visits and extracts content from entire websites. Give it a starting URL, and it automatically discovers pages through sitemaps and internal links, then extracts clean structured data from every page it visits.
## Quick Start
### Example Request
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.crawl.run(
url="https://www.nimbleway.com",
limit=10
)
print(f"Crawl started with ID: {result.crawl_id}")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.crawl.run({
url: "https://www.nimbleway.com",
limit: 10,
});
console.log(`Crawl started with ID: ${result.crawl_id}`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/crawl' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.nimbleway.com",
"limit": 10
}'
```
### Example Response
```json theme={"system"}
{
"crawl_id": "e3ca2ff1-b82a-472b-b1a9-ef4d29cc549f",
"name": null,
"url": "https://www.nimbleway.com",
"status": "queued",
"account_name": "your-account",
"created_at": "2026-02-09T23:15:40.785Z",
"updated_at": "2026-02-09T23:15:40.785Z",
"completed_at": null,
"crawl_options": {
"sitemap": "include",
"crawl_entire_domain": false,
"limit": 10,
"max_discovery_depth": 5,
"ignore_query_parameters": false,
"allow_external_links": false,
"allow_subdomains": false
},
"extract_options": null
}
```
## How it works
Provide a starting URL and configure crawl options (limits, filters,
extraction settings)
* Returns immediately with a `crawl_id` to track progress - The crawl runs
in the background on Nimble's infrastructure - Optional: Configure webhooks
to receive real-time notifications
* Reads sitemaps and follows internal links - Creates individual tasks for
each discovered URL - Extracts content from pages as they're visited -
Status updates live: track `pending`, `completed`, and `failed` counts
* Poll crawl status to monitor progress - Fetch extracted content for
completed tasks using `task_id` - Results persist after crawl completes for
later retrieval
## Parameters
Supported input parameters:
The starting point for your crawl. The crawler will begin here and discover other pages from this URL.
**Example:** `https://www.nimbleway.com`
Give your crawl a memorable name. This helps you identify it later when you have multiple crawls running.
**Example:** `my-zillow-crawl`
Stop the crawl after finding this many pages.
* Min: `1`
* Max: `10000`
* Default: `5000`
Automatically extract content from each page as you crawl it. Accepts all [Extract API](/nimble-sdk/web-tools/extract/quickstart) options.
\*\*Example: \*\*
```json theme={"system"}
{
"extract_options":{
"driver":"vx10",
"parse":true,
"formats": ["html", "markdown"]
}
}
```
Decide how to use the website's sitemap for discovering pages.
**Options:**
* `include` (default) - Use both the sitemap and discovered links
* `only` - Just use the sitemap (fastest)
* `skip` - Ignore the sitemap and only follow links
Let the crawler explore the entire domain, not just pages "under" your starting URL.
For example, if you start at `/blog`, enabling this lets it also crawl `/about` and `/contact`.
Allow the crawler to follow links to subdomains.
For example, from `www.example.com` to `blog.example.com` or `shop.example.com`.
Only crawl pages whose URLs match these regex patterns.
**Example:** `["/blog/.*", "/articles/.*"]`
Skip pages whose URLs match these regex patterns.
**Example:** `[".*/tag/.*", ".*/page/[0-9]+"]`
Control how many "clicks away" from the starting page the crawler can go.
* Min: `1`
* Max: `20`
* Default: `5`
Treat URLs with different query parameters as the same page, preventing duplicate crawls.
Get notified when your crawl completes or as pages are discovered.
**Configuration:**
* `url` (required) - String | Webhook URL to receive notifications
* `headers` - Object | Custom headers for authentication
* `metadata` - Object | Extra data to include in payloads
* `events` - Array | Which events trigger notifications: `started`, `page`, `completed`, `failed`
**Example:**
```json theme={"system"}
{
"callback":{
"url":"",
"headers":{},
"metadata":{},
"events":["started", "completed"]
}
}
```
Crawl the site as if you're browsing from a specific country.
Use ISO Alpha-2 country codes like `US`, `GB`, `FR`, `DE`, `CA`, `JP`, etc. Use `ALL` for random country selection.
Set the language preference for crawling. Use LCID standard.
**Locale Examples:**
* `en-US` - English (United States)
* `en-GB` - English (United Kingdom)
* `fr-FR` - French (France)
* `de-DE` - German (Germany)
## Usage
### Basic crawl
Crawl a website using default settings:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.crawl.run(url="https://www.nimbleway.com")
print(f"Crawl started with ID: {result.crawl_id}")
print(f"Status: {result.status}")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.crawl.run({
url: "https://www.nimbleway.com",
});
console.log(`Crawl started with ID: ${result.crawl_id}`);
console.log(`Status: ${result.status}`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/crawl' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.nimbleway.com"
}'
```
### Filter with URL patterns
Use include and exclude patterns to control which URLs are crawled:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.crawl.run(
url="https://www.nimbleway.com",
include_paths=["/blog/.*", "/use-cases/.*"],
exclude_paths=[".*/careers/.*"],
limit=500
)
print(f"Crawl ID: {result.crawl_id}")
print(f"Status: {result.status}")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.crawl.run({
url: "https://www.nimbleway.com",
include_paths: ["/blog/.*", "/use-cases/.*"],
exclude_paths: [".*/careers/.*"],
limit: 500,
});
console.log(`Crawl ID: ${result.crawl_id}`);
console.log(`Status: ${result.status}`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/crawl' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.nimbleway.com",
"include_paths": ["/blog/.*", "/use-cases/.*"],
"exclude_paths": [".*/careers/.*"],
"limit": 500
}'
```
### Crawl entire domain
Allow crawler to follow all internal links beyond the starting path:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.crawl.run(
url="https://www.nimbleway.com/blog",
crawl_entire_domain=True,
limit=2000
)
print(f"Crawl ID: {result.crawl_id}")
print(f"Status: {result.status}")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.crawl.run({
url: "https://www.nimbleway.com/blog",
crawl_entire_domain: true,
limit: 2000,
});
console.log(`Crawl ID: ${result.crawl_id}`);
console.log(`Status: ${result.status}`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/crawl' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.nimbleway.com/blog",
"crawl_entire_domain": true,
"limit": 2000
}'
```
### Crawl with extraction
Extract structured data from each page during the crawl:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.crawl.run(
url="https://www.nimbleway.com",
limit=500,
extract_options={
"driver": "vx10",
"parse": True,
"formats": ["html", "markdown"]
}
)
print(f"Crawl ID: {result.crawl_id}")
print(f"Status: {result.status}")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.crawl.run({
url: "https://www.nimbleway.com",
limit: 500,
extract_options: {
driver: "vx10",
parse: true,
formats: ["html", "markdown"],
},
});
console.log(`Crawl ID: ${result.crawl_id}`);
console.log(`Status: ${result.status}`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/crawl' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.nimbleway.com",
"limit": 500,
"extract_options": {
"driver": "vx10",
"parse": true,
"formats": ["html", "markdown"]
}
}'
```
### Combined parameters
Crawl with multiple parameters for precise control:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.crawl.run(
url="https://www.nimbleway.com",
name="Nimble Website Crawl",
sitemap="include",
allow_subdomains=True,
include_paths=["/use-cases/.*"],
limit=1000,
callback={
"url": "https://your-server.com/webhook",
"events": ["completed"]
}
)
print(f"Crawl started: {result.crawl_id}")
print(f"Status: {result.status}")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.crawl.run({
url: "https://www.nimbleway.com",
name: "Nimble Website Crawl",
sitemap: "include",
allow_subdomains: true,
include_paths: ["/use-cases/.*"],
limit: 1000,
callback: {
url: "https://your-server.com/webhook",
events: ["completed"],
},
});
console.log(`Crawl started: ${result.crawl_id}`);
console.log(`Status: ${result.status}`);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/crawl' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.nimbleway.com",
"name": "Nimble Website Crawl",
"sitemap": "include",
"allow_subdomains": true,
"include_paths": ["/use-cases/.*"],
"limit": 1000,
"callback": {
"url": "https://your-server.com/webhook",
"events": ["completed"]
}
}'
```
## Managing Crawls
Get all your crawls filtered by status using the REST API:
* **Available status filters:** `pending`, `in_progress`, `completed`, `failed`, `canceled`
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# List crawls by status
my_crawls = nimble.crawl.list()
for crawl in my_crawls.data:
print(f"Crawl {crawl.crawl_id}: {crawl.name} - {crawl.status}")
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// List crawls by status
const myCrawls = await nimble.crawl.list();
myCrawls.data.forEach(crawl => {
console.log(`Crawl ${crawl.crawl_id}: ${crawl.name} - ${crawl.status}`);
});
```
```bash cURL theme={"system"}
# Filter by status: pending, in_progress, completed, failed, canceled
curl -X GET 'https://sdk.nimbleway.com/v1/crawl?status=completed' \
--header 'Authorization: Bearer '
```
Check progress and get the list of task IDs for a specific crawl using the REST API:
```python Python theme={"system"}
my_crawl = nimble.crawl.status(crawl_id)
print(f"Status: {my_crawl.status}")
```
```javascript Node theme={"system"}
const myCrawl = await nimble.crawl.status(crawlId);
console.log(`Status: ${myCrawl.status}`);
```
```bash cURL theme={"system"}
curl -X GET 'https://sdk.nimbleway.com/v1/crawl/e3ca2ff1-b82a-472b-b1a9-ef4d29cc549f' \
--header 'Authorization: Bearer '
```
Use the `task_id` from the crawl status response to fetch extracted content for each page using the REST API:
```python Python theme={"system"}
# my_crawl["tasks"] from step #2 contains list of task IDs from status response
for task in my_crawl.tasks:
if task.status == "completed":
task_result = nimble.tasks.get(task_id)
print(f"URL: {task_result['url']}")
print(f"HTML length: {len(task_result['data'].get('html', ''))}")
```
```javascript Node theme={"system"}
// myCrawl.tasks from step #2 contains list of task IDs from status response
for (const task of myCrawl.tasks) {
if (task.status === "completed") {
const taskResponse = await nimble.tasks.get(taskId);
console.log(`URL: ${taskResult.url}`);
console.log(`HTML length: ${taskResult.data?.html?.length || 0}`);
}
}
```
```bash cURL theme={"system"}
# Get results for each task_id from the crawl status response
curl 'https://sdk.nimbleway.com/v1/tasks/{task_id}/results' \
--header 'Authorization: Bearer YOUR-API-KEY'
```
```json theme={"system"}
{
"url": "https://www.nimbleway.com/blog/post",
"task_id": "ec89b1f7-1cf2-40eb-91b4-78716093f9ed",
"status": "success",
"task": {
"id": "ec89b1f7-1cf2-40eb-91b4-78716093f9ed",
"state": "success",
"created_at": "2026-02-09T23:15:43.549Z",
"modified_at": "2026-02-09T23:16:39.094Z",
"account_name": "your-account"
},
"data": {
"html": "...",
"markdown": "# Page Title\n\nContent...",
"headers": { ... }
},
"metadata": {
"query_time": "2026-02-09T23:15:43.549Z",
"query_duration": 1877,
"response_parameters": {
"input_url": "https://www.nimbleway.com/blog/post"
},
"driver": "vx6"
},
"status_code": 200
}
```
Stop a running crawl using the REST API. Completed tasks remain available for result retrieval:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
response = nimble.crawl.terminate(crawl_id)
print(response) # {"status": "canceled"}
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const response = await nimble.crawl.terminate(crawlId);
console.log(await response); // { status: "canceled" }
```
```bash cURL theme={"system"}
curl -X DELETE 'https://sdk.nimbleway.com/v1/crawl/e3ca2ff1-b82a-472b-b1a9-ef4d29cc549f' \
--header 'Authorization: Bearer '
```
## Response Fields
When you use **Crawl**, you receive:
* **Async operation** - Crawl jobs run in the background, check status or receive webhooks
* **Progress tracking** - Monitor `total`, `pending`, `completed`, and `failed` counts
* **Task-based results** - Each page becomes a task with extractable content
* **Webhook support** - Get notified in real-time as pages are processed
### Create Crawl Response
Returns immediate response with crawl job details
```json theme={"system"}
{
"crawl_id": "e3ca2ff1-b82a-472b-b1a9-ef4d29cc549f",
"name": null,
"url": "https://www.nimbleway.com",
"status": "queued",
"account_name": "your-account",
"created_at": "2026-02-09T23:15:40.785Z",
"updated_at": "2026-02-09T23:15:40.785Z",
"completed_at": null,
"crawl_options": {
"sitemap": "include",
"crawl_entire_domain": false,
"limit": 10,
"max_discovery_depth": 5,
"ignore_query_parameters": false,
"allow_external_links": false,
"allow_subdomains": false
},
"extract_options": null
}
```
| Field | Type | Description |
| ----------------- | ------ | ------------------------------------------------------ |
| `crawl_id` | string | Unique identifier for the crawl job |
| `name` | string | Optional name you assigned to the crawl |
| `url` | string | Starting URL for the crawl |
| `status` | string | `queued`, `running`, `succeeded`, `failed`, `canceled` |
| `account_name` | string | Your account identifier |
| `created_at` | string | Timestamp when crawl was created |
| `updated_at` | string | Timestamp of last status update |
| `completed_at` | string | Timestamp when crawl completed (null if in progress) |
| `crawl_options` | object | Configuration settings applied to this crawl |
| `extract_options` | object | Extraction settings (null if not configured) |
### Get Crawl Status by ID Response
Returns the crawl object wrapped in a `crawl` key, with progress counters and task list:
```json theme={"system"}
{
"crawl": {
"crawl_id": "e3ca2ff1-b82a-472b-b1a9-ef4d29cc549f",
"name": null,
"url": "https://www.nimbleway.com",
"status": "succeeded",
"account_name": "your-account",
"total": 10,
"pending": 0,
"completed": 10,
"failed": 0,
"created_at": "2026-02-09T23:15:40.785Z",
"updated_at": "2026-02-09T23:17:08.083Z",
"completed_at": "2026-02-09T23:17:08.079Z",
"crawl_options": {
"sitemap": "include",
"crawl_entire_domain": false,
"limit": 10,
"max_discovery_depth": 5
},
"extract_options": null,
"tasks": [
{
"task_id": "ec89b1f7-1cf2-40eb-91b4-78716093f9ed",
"status": "completed",
"updated_at": "2026-02-09T23:16:39.094Z",
"created_at": "2026-02-09T23:15:43.549Z"
},
{
"task_id": "3f6c136c-4bb5-44af-a21b-c8f1db708c2f",
"status": "completed",
"updated_at": "2026-02-09T23:16:45.033Z",
"created_at": "2026-02-09T23:15:42.966Z"
}
]
}
}
```
| Field | Type | Description |
| ----------------------- | ------- | ------------------------------------------------ |
| `crawl.crawl_id` | string | Unique identifier for the crawl job |
| `crawl.status` | string | Current crawl status |
| `crawl.total` | integer | Total URLs discovered |
| `crawl.pending` | integer | URLs waiting to be processed |
| `crawl.completed` | integer | Successfully processed URLs |
| `crawl.failed` | integer | Failed URL extractions |
| `crawl.tasks` | array | List of individual page tasks |
| `crawl.tasks[].task_id` | string | Task ID to use with `GET /v1/tasks/{id}/results` |
| `crawl.tasks[].status` | string | `pending`, `processing`, `completed`, `failed` |
## SDK and API methods
| Method | Availability | Description |
| :-------------------------------- | :----------- | :------------------------------- |
| `nimble.crawl.run(url=..., ...)` | Python SDK | Create a new crawl job |
| `GET /v1/crawl` | REST API | List all crawls with pagination |
| `GET /v1/crawl/{crawl_id}` | REST API | Get crawl status and task list |
| `DELETE /v1/crawl/{crawl_id}` | REST API | Stop a running crawl |
| `GET /v1/tasks/{task_id}/results` | REST API | Get extracted content for a page |
The Python SDK currently supports creating crawl jobs via
`nimble.crawl.run()`. For crawl management operations (listing, status,
cancellation) and retrieving task results, use the REST API directly as shown
in the examples above.
## Use cases
Extract data from hundreds or thousands of pages across an entire website
Gather all product information from e-commerce sites automatically
Create complete snapshots of websites for analysis or backup
Track pricing across entire catalogs over time
### Real-world examples
**Scenario:** You need to gather all product information from a competitor's online store.
**How Crawl helps:**
* Discovers all product pages through sitemaps and navigation
* Extracts product details, prices, and descriptions from each page
* Handles pagination and category structures automatically
* Filters out cart, checkout, and account pages
**Result:** Complete product catalog data without manual URL collection.
**Scenario:** You're migrating a blog to a new platform and need all content.
**How Crawl helps:**
* Finds all blog posts through sitemap and internal links
* Extracts post content, metadata, and images
* Excludes tag pages, author archives, and pagination
* Preserves URL structure for redirects
**Result:** Complete content export ready for migration.
**Scenario:** You want to create an offline backup of documentation.
**How Crawl helps:**
* Maps entire documentation structure
* Extracts content from all pages
* Maintains hierarchy and navigation structure
* Captures code examples and technical content
**Result:** Complete documentation archive for offline access.
**Scenario:** You need to track competitor pricing across their entire catalog.
**How Crawl helps:**
* Discovers all product pages automatically
* Extracts pricing information from each page
* Runs on schedule to track changes over time
* Handles dynamic pricing and regional variations
**Result:** Comprehensive price intelligence data.
**Scenario:** You're auditing a website's content for SEO optimization.
**How Crawl helps:**
* Discovers all indexable pages
* Extracts titles, meta descriptions, and headings
* Identifies orphaned pages and broken links
* Maps internal linking structure
**Result:** Complete SEO audit data for analysis.
## Crawl vs Map
| Need | Use |
| --------------------------------- | ------------------------------ |
| Extract content from pages | **Crawl** |
| Deep link following | **Crawl** |
| Complex filtering patterns | **Crawl** |
| Webhook notifications | **Crawl** |
| Quick URL discovery only | **Map** - completes in seconds |
| URL list with titles/descriptions | **Map** |
**Try Use Map first** - Discover URLs quickly with Map, then use Crawl to
extract content from the pages you need.
## Next steps
Explore endpoints, request parameters, and response schemas for the Crawl
API
# Async Requests
Source: https://docs.nimbleway.com/nimble-sdk/web-tools/extract/features/async
Run extraction tasks asynchronously for large-scale operations
Use async requests when you need to extract data from multiple pages, run long-running operations, or integrate extraction into background job systems. Async requests return immediately with a task ID, letting you check status and retrieve results later.
## When to use async
Use async extract when you:
* **Background jobs**: Integrate extraction into scheduled or queued workflows
* **Long-running operations**: Handle complex browser actions or slow-loading sites
* **Webhook integration**: Get notified when extraction completes
* **Cloud storage**: Save results directly to S3 or Google Cloud Storage
Async requests are ideal for high-volume extraction where you don't need
immediate results. For single-page extractions where you need results right
away, use the synchronous [Extract
API](/nimble-sdk/web-tools/extract/quickstart).
## How it works
Send a POST request to `/v1/extract/async` with your extraction parameters. The API returns immediately with a task ID.
Optionally include:
* `callback_url` to receive a webhook notification when complete
* `storage_url` and `storage_type` (s3/gs) to save results directly to cloud storage
Use the task ID to check progress at `/v1/tasks/{task_id}`. The task transitions through states: `pending` → `completed` or `failed`.
Once complete, fetch results from `/v1/tasks/{task_id}/results` or from your configured cloud storage.
## API endpoint
```bash theme={"system"}
POST https://sdk.nimbleway.com/v1/extract/async
```
## Parameters
Async extract accepts all the same parameters as the synchronous extract endpoint, plus optional async-specific parameters:
### Core extraction parameters
All parameters from the [Extract API](/nimble-sdk/web-tools/extract/quickstart) are supported:
* `url` (required) - The webpage to extract
* `formats` - Output formats (html, markdown, text, screenshot)
* `render` - Enable JavaScript rendering
* `driver` - Choose extraction engine (vx6, vx8, vx10, etc.)
* `country`, `state`, `city` - Geo-targeting options
* `parse` - Enable parsing with schemas
* `parser` - Define extraction schema
* `browser_actions` - Automate interactions
* `network_capture` - Capture network requests
* And all other extract parameters...
### Async-specific parameters
Storage provider for results. When specified, results are saved to your cloud storage instead of Nimble's servers.
**Options:** `s3` (Amazon S3), `gs` (Google Cloud Storage)
Bucket path where results will be saved. Results are stored as `{task_id}.json` at the specified location.
**Format:** `s3://your-bucket/path/prefix/`
**Example:** `s3://my-bucket/nimble-results/`
Compress results with GZIP before saving. Reduces storage costs and transfer time. When `true`, results are saved as `{task_id}.json.gz`.
Custom filename for the stored object instead of the default task ID.
**Example:** `"my-custom-name"` saves as `my-custom-name.json`
Webhook URL to receive a POST request when the task completes. Nimble sends task metadata (without result data) to this URL when extraction finishes.
**Example:** `https://your-api.com/webhook/complete`
## Response format
The async endpoint returns immediately with task information:
```json theme={"system"}
{
"task": {
"id": "8e8cfde8-345b-42b8-b3e2-0c61eb11e00f",
"state": "completed",
"status_code": 200,
"created_at": "2026-01-24T12:36:24.685Z",
"modified_at": "2026-01-24T12:36:24.685Z",
"input": {},
"api_type": "extract"
}
}
```
### Task states
| State | Description |
| --------- | --------------------------------------------------- |
| `pending` | Task queued, waiting to start |
| `running` | Extraction in progress |
| `success` | Extraction finished successfully, results available |
| `failed` | Extraction failed, check error details |
## Example usage
### Basic async extraction
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR_API_KEY")
# Submit async extraction
response = nimble.extract_async(
url= "https://www.example.com",
render= True,
formats= ["html", "markdown"]
)
task_id = response.task_id
print(f"Task created: {task_id}")
# Check status
import time
while True:
my_task = nimble.tasks.get(task_id)
print(f"Status: {my_task.task.state}")
if my_task.task.state == 'success':
# Get results
results = nimble.tasks.results(task_id)
print(results.data.html[:200])
break
elif my_task.task.state == 'failed':
print(f"Task failed: {my_task.message}")
break
time.sleep(2)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR_API_KEY" });
// Submit async extraction
const response = await nimble.extractAsync({
url: "https://www.example.com",
render: true,
formats: ["html", "markdown"],
});
const taskId = response.task_id;
console.log(`Task created: ${taskId}`);
// Check status
while (true) {
const myTask = await nimble.tasks.get(taskId);
console.log(`Status: ${myTask.task.state}`);
if (myTask.task.state === "success") {
// Get results
const results = await nimble.tasks.results(taskId);
console.log(results.data.html.substring(0, 200));
break;
} else if (myTask.task.state === "failed") {
console.log(`Task failed: ${status.error}`);
break;
}
await new Promise((resolve) => setTimeout(resolve, 2000));
}
```
```bash cURL theme={"system"}
# Submit async extraction
curl -X POST 'https://sdk.nimbleway.com/v1/extract/async' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"formats": ["html", "markdown"]
}'
# Response:
# {
# "task": {
# "id": "f32e1196-3827-4b3a-b6ad-89c51040a2ab",
# "state": "pending",
# "created_at": "2026-02-18T17:17:28.020Z",
# "modified_at": "2026-02-18T17:17:28.020Z",
# "account_name": "account_name",
# "input": {
# "url": "https://www.google.com/search?q=trump",
# "country": "US",
# "locale": "en-US",
# "driver": "vx6"
# },
# "api_type": "extract"
# }
# }
# Check status
curl 'https://sdk.nimbleway.com/v1/tasks/8e8cfde8-345b-42b8-b3e2-0c61eb11e00f' \
--header 'Authorization: Bearer YOUR_API_KEY'
# Get results (when completed)
curl 'https://sdk.nimbleway.com/v1/tasks/8e8cfde8-345b-42b8-b3e2-0c61eb11e00f/results' \
--header 'Authorization: Bearer YOUR_API_KEY'
```
### Save to cloud storage
Store results directly in Amazon S3:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR_API_KEY")
response = nimble.extract_async(
url= "https://www.example.com",
render= True,
formats= ["html", "markdown"],
storage_type= "s3",
storage_url= "s3://my-bucket/nimble-extracts/",
storage_compress= True,
storage_object_name= "example-com-extraction"
)
task_id = response.task_id
print(f"Task created: {task_id}")
print(f"Results will be saved to: s3://my-bucket/nimble-extracts/example-com-extraction.json.gz")
# Results are automatically saved to S3 when complete
# You can still check status and retrieve from Nimble's servers if needed
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR_API_KEY" });
// Submit async extraction
const response = await nimble.extractAsync({
url: "https://www.example.com",
render: true,
formats: ["html", "markdown"],
storage_type: "s3",
storage_url: "s3://my-bucket/nimble-extracts/",
storage_compress: True,
storage_object_name: "example-com-extraction",
});
const taskId = response.task_id;
console.log(`Task created: ${taskId}`);
console.log(
"Results will be saved to: s3://my-bucket/nimble-extracts/example-com-extraction.json.gz",
);
// Results are automatically saved to S3 when complete
// You can still check status and retrieve from Nimble's servers if needed
```
```bash cURL theme={"system"}
# Submit async extraction
curl -X POST 'https://sdk.nimbleway.com/v1/extract/async' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"formats": ["html", "markdown"],
"storage_type": "s3",
"storage_url": "s3://my-bucket/nimble-extracts/",
"storage_compress": True,
"storage_object_name": "example-com-extraction"
}'
# Results are automatically saved to S3 when complete
# You can still check status and retrieve from Nimble's servers if needed
```
### Webhook notifications
Get notified when extraction completes:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR_API_KEY")
response = nimble.extract_async(
url= "https://www.example.com",
render= True,
formats= ["html"],
callback_url= "https://your-api.com/webhooks/extract-complete"
)
task_id = response.task_id
print(f"Task created: {task_id}")
print("Webhook will be called when extraction completes")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR_API_KEY" });
// Submit async extraction
const response = await nimble.extractAsync({
url: "https://www.example.com",
render: true,
formats: ["html", "markdown"],
callback_url: "https://your-api.com/webhooks/extract-complete",
});
const taskId = response.task_id;
console.log(`Task created: ${taskId}`);
console.log("Webhook will be called when extraction completes");
```
```bash cURL theme={"system"}
# Submit async extraction
curl -X POST 'https://sdk.nimbleway.com/v1/extract/async' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"formats": ["html", "markdown"],
"callback_url": "https://your-api.com/webhooks/extract-complete"
}'
# Webhook will be called when extraction completes
```
## Checking task status
Use the Tasks API to check status:
```bash theme={"system"}
GET https://sdk.nimbleway.com/v1/tasks/{task_id}/results
```
### Status Response:
```json theme={"system"}
{
"task": {
"id": "8e8cfde8-345b-42b8-b3e2-0c61eb11e00f",
"state": "completed",
"status_code": 200,
"created_at": "2026-01-24T12:36:24.685Z",
"modified_at": "2026-01-24T12:36:24.685Z",
"input": {},
"api_type": "extract"
}
}
```
## Retrieving results
Once the task is complete, retrieve results:
```bash theme={"system"}
GET https://sdk.nimbleway.com/v1/tasks/{task_id}/results
```
### Results Response
```json theme={"system"}
{
"url": "https://www.nimbleway.com/blog/post",
"task_id": "ec89b1f7-1cf2-40eb-91b4-78716093f9ed",
"status": "success",
"task": {
"id": "ec89b1f7-1cf2-40eb-91b4-78716093f9ed",
"state": "success",
"created_at": "2026-02-09T23:15:43.549Z",
"modified_at": "2026-02-09T23:16:39.094Z",
"account_name": "your-account"
},
"data": {
"html": "...",
"markdown": "# Page Title\n\nContent...",
"headers": { ... }
},
"metadata": {
"query_time": "2026-02-09T23:15:43.549Z",
"query_duration": 1877,
"response_parameters": {
"input_url": "https://www.nimbleway.com/blog/post"
},
"driver": "vx6"
},
"status_code": 200
}
```
## Data Retention & Expiration
### Result retention
Results are typically retained for 7 days. If you need longer retention:
* Use cloud storage (`storage_url`) to persist results indefinitely
* Download results promptly after completion
* Implement your own archival system
### Task expiration
* **Pending tasks**: Expire after 24 hours if not started
* **Completed results**: Available for 24-48 hours (unless using cloud storage)
* **Failed tasks**: Retry data available for 24 hours
# Browser Actions
Source: https://docs.nimbleway.com/nimble-sdk/web-tools/extract/features/browser-actions
Full control over browser actions with predefined steps
**Browser Actions** gives you full control over the sequence of actions performed in the browser, ensuring predictable and repeatable results. You manually specify each step like click, scroll, wait, or type.
Common uses:
* **Load more content**: Click "Show more" buttons or scroll to reveal additional items.
* **Set filters**: Select dropdowns, checkboxes, or date ranges to refine displayed data.
* **Submit searches**: Enter search terms and submit forms to access results pages.
* **Trigger lazy-loaded data**: Scroll to load images, products, or infinite feeds.
## When to use
Use Browser Actions when you need:
* **Predictable execution**: Same steps run every time
* **Full control**: Specify exact actions and sequences
* **Fast performance**: No AI inference overhead
Browser Action flows may break when page structure or selectors change.
Monitor and update your flows as needed.
## Parameters
**`Must be set to true`** to use browser actions. This enables the browser to execute JavaScript and perform interactions.
Browser actions only work when the page is rendered in a real browser environment.
**Example:**
```json theme={"system"}
"render": true
```
A list of actions to perform in sequence on the page. Each action is an object specifying what to do (click, scroll, wait, type, etc.).
**Actions execute in order** - the second action waits for the first to complete, and so on.
**Global timeout:** All actions must complete within 240 seconds total.
**Available actions:**
* `goto` - Navigate to a different URL
* `wait` - Pause for a specified duration
* `wait_for_element` - Wait for an element to appear
* `click` - Click an element
* `press` - Press a keyboard key (Enter, Tab, Escape, etc.)
* `fill` - Type or paste text into an input field
* `scroll` - Scroll the page by pixels or to an element
* `auto_scroll` - Automatically scroll to load lazy content
* `screenshot` - Capture a screenshot
* `get_cookies` - Extract cookies from the page
* `fetch` - Make HTTP requests from the browser context
Each action has specific parameters detailed in the sections below.
**Example:**
```json theme={"system"}
"browser_actions": [
{
"fill": {
"selector": "input[type='search']",
"value": "laptops"
}
},
{
"click": {
"selector": "button[type='submit']"
}
},
{
"wait": "2s"
}
]
```
All browser actions execute sequentially within a global **240-second
timeout**. If any action fails, the entire flow stops unless marked as
optional.
## Usage
Navigate to a different URL during the browser session.
**Parameters:**
**Direct form** - Pass URL as a string:
* `goto` (required) - URL to navigate to
**Extended form** - Use object with options:
* `url` (required) - URL to navigate to (string)
* `timeout` (optional) - Maximum wait time in milliseconds (number, default: 30000)
* `referer` (optional) - HTTP referer header to send (string)
* `wait_until` (optional) - Navigation wait condition: `'load'` (default), `'domcontentloaded'`, `'networkidle'`, or `'commit'`
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Direct form - simple navigation
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"goto": "https://www.example.com/products" # Navigate to products page
}
]
)
# Extended form - with wait condition
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"goto": {
"url": "https://www.example.com/products",
"wait_until": "networkidle",
"timeout": 5000,
"referer": "https://www.google.com"
}
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Direct form - simple navigation
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
goto: "https://www.example.com/products" // Navigate to products page
}
]
});
// Extended form - with wait condition
const result2 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
goto: {
url: "https://www.example.com/products",
wait_until: "networkidle",
timeout: 5000,
referer: "https://www.google.com"
}
}
]
});
console.log(result);
```
```bash cURL theme={"system"}
# Direct form
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"goto": "https://www.example.com/products"
}]
}'
# Extended form
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"goto": {
"url": "https://www.example.com/products",
"wait_until": "networkidle",
"timeout": 5000,
"referer": "https://www.google.com"
}
}]
}'
```
Add a delay between actions to simulate human behavior or allow elements to load.
**Parameters:**
**Direct form** - Pass duration as a string:
* `wait` (required) - Duration string (e.g., "2s", "500ms", "1.5s")
**Extended form** - Use object with options:
* `duration` (required) - Duration string (e.g., "2s", "500ms", "1.5s")
* `required` (optional) - Set to `false` to make this step optional (boolean, default: `true`)
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Direct form - simple delay
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"wait": "2s" # Wait for 2 seconds
}
]
)
# Extended form - with options
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"wait": {
"duration": "500ms",
"required": False
}
}
]
)
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Direct form - simple delay
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
wait: "2s" // Wait for 2 seconds
}
]
});
// Extended form - with options
const result2 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
wait: {
duration: "500ms",
required: false
}
}
]
});
```
```bash cURL theme={"system"}
# Direct form
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"wait": "2s"
}]
}'
# Extended form
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"wait": {
"duration": "500ms",
"required": false
}
}]
}'
```
Wait for DOM elements to appear on the page.
**Parameters:**
**Direct form** - Pass single selector or array of selectors:
* `wait_for_element` (required) - CSS selector string or array of selectors to wait for (any one matching triggers success)
**Extended form** - Use object with options:
* `selector` (required) - CSS selector string or array of selectors to wait for
* `timeout` (optional) - Maximum time in milliseconds to wait (number, default: 30000)
* `visible` (optional) - Whether element must be visible (boolean, default: `true`)
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Direct form - wait for single element
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"wait_for_element": "#submit-button"
}
]
)
# Direct form - wait for multiple elements
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"wait_for_element": ["#element1", ".class2"]
}
]
)
# Extended form - with options
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"wait_for_element": {
"selector": "#element",
"timeout": 30000,
"visible": False
}
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Direct form - wait for single element
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
wait_for_element: "#submit-button"
}
]
});
// Direct form - wait for multiple elements
const result2 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
wait_for_element: ["#element1", ".class2"]
}
]
});
// Extended form - with options
const result3 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
wait_for_element: {
selector: "#element",
timeout: 30000,
visible: false
}
}
]
});
console.log(result);
```
```bash cURL theme={"system"}
# Direct form - single selector
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"wait_for_element": "#submit-button"
}]
}'
# Direct form - multiple selectors
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"wait_for_element": ["#element1", ".class2"]
}]
}'
# Extended form
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"wait_for_element": {
"selector": "#element",
"timeout": 30000,
"visible": false
}
}]
}'
```
Click on an element by selector or at specific coordinates.
**Parameters:**
**Direct form** - Pass CSS selector as string:
* `click` (required) - CSS selector string
**Extended form (selector mode)** - Use object with selector options:
* `selector` (required) - CSS selector of element to click (string)
* `timeout` (optional) - Maximum time to wait for element (Duration string, default: "30s")
* `visible` (optional) - Whether element must be visible (boolean, default: `true`)
* `delay` (optional) - Delay before clicking (Duration string, default: "0ms")
* `scroll` (optional) - Whether to scroll element into view (boolean, default: `true`)
* `count` (optional) - Number of times to click (number, default: 1)
* `steps` (optional) - Mouse movement steps for granular control (number, advanced)
* `strategy` (optional) - Mouse movement strategy for behavioral simulation (advanced)
* `required` (optional) - Set to `false` to make this step optional (boolean, default: `true`)
**Extended form (coordinates mode)** - Click at specific coordinates:
* `x` (required) - X coordinate (horizontal position, number)
* `y` (required) - Y coordinate (vertical position, number)
* `relative_to` (optional) - CSS selector to make coordinates relative to this element (string)
* `timeout` (optional) - Maximum time for the click operation (Duration string, default: "15s")
* `delay` (optional) - Delay before clicking (Duration string, default: "0ms")
* `count` (optional) - Number of times to click (number, default: 1)
* `steps` (optional) - Mouse movement steps for granular control (number, advanced)
* `required` (optional) - Set to `false` to make this step optional (boolean, default: `true`)
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Direct form - simple click by selector
result = nimble.extract(
"url": "https://www.example.com",
"render": True,
"browser_actions": [
{
"click": "button.submit" # Click element matching selector
}
]
)
# Extended form (selector mode) - with options
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"click": {
"selector": "button.load-more",
"timeout": "20s",
"delay": "500ms",
"scroll": True,
"visible": True,
"count": 2 # Double-click
}
}
]
)
# Extended form (coordinates mode) - click at specific position
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"click": {
"x": 100,
"y": 200,
"delay": "300ms"
}
}
]
)
# Coordinates relative to element
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"click": {
"x": 10,
"y": 10,
"relative_to": "#container" # Click 10px from top-left of container
}
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Direct form - simple click by selector
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
click: "button.submit" // Click element matching selector
}
]
});
// Extended form (selector mode) - with options
const result2 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
click: {
selector: "button.load-more",
timeout: "20s",
delay: "500ms",
scroll: true,
visible: true,
count: 2 // Double-click
}
}
]
});
// Extended form (coordinates mode) - click at specific position
const result3 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
click: {
x: 100,
y: 200,
delay: "300ms"
}
}
]
});
// Coordinates relative to element
const result4 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
click: {
x: 10,
y: 10,
relative_to: "#container" // Click 10px from top-left of container
}
}
]
});
console.log(result);
```
```bash cURL theme={"system"}
# Direct form - simple click by selector
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"click": "button.submit"
}]
}'
# Extended form (selector mode) - with options
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"click": {
"selector": "button.load-more",
"timeout": "20s",
"delay": "500ms",
"scroll": true,
"visible": true,
"count": 2
}
}]
}'
# Extended form (coordinates mode) - click at specific position
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"click": {
"x": 100,
"y": 200,
"delay": "300ms"
}
}]
}'
# Coordinates relative to element
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"click": {
"x": 10,
"y": 10,
"relative_to": "#container"
}
}]
}'
```
Press a keyboard key like Enter, Tab, Escape, or arrow keys.
**Parameters:**
**Direct form** - Pass key name as a string:
* `press` (required) - Key name to press (e.g., "Enter", "Tab", "Escape", "ArrowDown")
**Extended form** - Use object with options:
* `key` (required) - Key name to press (string)
* `delay` (optional) - Delay in milliseconds before pressing (number, default: 0)
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Direct form - press Enter key
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"press": "Enter" # Press Enter key
}
]
)
# Extended form - press with delay
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"press": {
"key": "Tab",
"delay": 500
}
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Direct form - press Enter key
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
press: "Enter" // Press Enter key
}
]
});
// Extended form - press with delay
const result2 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
press: {
key: "Tab",
delay: 500
}
}
]
});
console.log(result);
```
```bash cURL theme={"system"}
# Direct form
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"press": "Enter"
}]
}'
# Extended form
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"press": {
"key": "Tab",
"delay": 500
}
}]
}'
```
Fill an input field with text. Supports both typing (character-by-character) and pasting (instant) modes.
**Parameters:**
**Extended form only** - No direct form available:
* `selector` (required) - CSS selector of the input element (string)
* `value` (required) - Text value to fill (string)
* `mode` (optional) - Fill mode: `'type'` for character-by-character (default), `'paste'` for instant (string)
* `timeout` (optional) - Maximum time to wait for element in milliseconds (number, default: 30000)
* `typing_interval` (optional) - Interval between keystrokes in milliseconds when typing (number, default: 100, min: 10, max: 1000)
* `click_on_element` (optional) - Whether to click on element to focus it (boolean, default: `true`)
* `scroll` (optional) - Whether to scroll element into view (boolean, default: `true`)
* `visible` (optional) - Whether element must be visible (boolean, default: `true`)
* `delay` (optional) - Delay in milliseconds before filling (number, default: 0)
* `mouse_movement_strategy` (optional) - Mouse movement strategy for behavioral simulation (advanced)
* `typing_strategy` (optional) - Typing strategy for behavioral simulation (advanced)
* `required` (optional) - Set to `false` to make this step optional (boolean, default: `true`)
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Type mode (default, character-by-character)
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"fill": {
"selector": "input[name='search']",
"value": "eggplant",
"mode": "type", # Default mode
"typing_interval": 100, # 100ms between keystrokes
"click_on_element": True,
"scroll": True
}
}
]
)
# Paste mode (instant, faster)
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"fill": {
"selector": "textarea",
"value": "Long text content...",
"mode": "paste", # Instant paste
"timeout": 30000
}
}
]
)
# Fill with options
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"fill": {
"selector": "input",
"value": "text",
"scroll": True,
"delay": 500,
"typing_interval": 150,
"visible": True
}
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Type mode (default, character-by-character)
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
fill: {
selector: "input[name='search']",
value: "eggplant",
mode: "type", // Default mode
typing_interval: 100, // 100ms between keystrokes
click_on_element: true,
scroll: true
}
}
]
});
// Paste mode (instant, faster)
const result2 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
fill: {
selector: "textarea",
value: "Long text content...",
mode: "paste", // Instant paste
timeout: 30000
}
}
]
});
// Fill with options
const result3 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
fill: {
selector: "input",
value: "text",
scroll: true,
delay: 500,
typing_interval: 150,
visible: true
}
}
]
});
console.log(result);
```
```bash cURL theme={"system"}
# Type mode (default)
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"fill": {
"selector": "input[name='\''search'\'']",
"value": "eggplant",
"mode": "type",
"typing_interval": 100,
"click_on_element": true,
"scroll": true
}
}]
}'
# Paste mode
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"fill": {
"selector": "textarea",
"value": "Long text content...",
"mode": "paste",
"timeout": 30000
}
}]
}'
# Fill with options
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"fill": {
"selector": "input",
"value": "text",
"scroll": true,
"delay": 500,
"typing_interval": 150,
"visible": true
}
}]
}'
```
Scroll the page by pixels, to a position, or to an element.
**Parameters:**
**Direct form** - Pass number or string:
* `scroll: 500` - Scroll Y pixels (number, positive = down, negative = up)
* `scroll: "bottom"` - Scroll to bottom of page (string)
* `scroll: "#comments"` - Scroll to element matching selector (string)
**Extended form** - Use object with options:
* `y` (optional) - Vertical scroll distance in pixels (number, default: 0)
* `x` (optional) - Horizontal scroll distance in pixels (number, default: 0)
* `to` (optional) - CSS selector to scroll to (string, alternative to x/y)
* `container` (optional) - CSS selector of container element to scroll within (string)
* `visible` (optional) - Whether element must be visible when scrolling to it (boolean, default: `true`)
* `required` (optional) - Set to `false` to make this step optional (boolean, default: `true`)
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Direct form - scroll down 500px
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"scroll": 500 # Scroll down 500 pixels
}
]
)
# Direct form - scroll up 200px
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"scroll": -200 # Scroll up 200 pixels
}
]
)
# Direct form - scroll to bottom
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"scroll": "bottom" # Scroll to page bottom
}
]
)
# Direct form - scroll to element
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"scroll": "#comments" # Scroll to comments section
}
]
)
# Extended form - scroll by pixels
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"scroll": {
"x": 100,
"y": 500
}
}
]
)
# Extended form - scroll to element in container
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"scroll": {
"to": "#target",
"container": "#modal",
"visible": True
}
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Direct form - scroll down 500px
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
scroll: 500 // Scroll down 500 pixels
}
]
});
// Direct form - scroll up 200px
const result2 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
scroll: -200 // Scroll up 200 pixels
}
]
});
// Direct form - scroll to bottom
const result3 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
scroll: "bottom" // Scroll to page bottom
}
]
});
// Direct form - scroll to element
const result4 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
scroll: "#comments" // Scroll to comments section
}
]
});
// Extended form - scroll by pixels
const result5 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
scroll: {
x: 100,
y: 500
}
}
]
});
// Extended form - scroll to element in container
const result6 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
scroll: {
to: "#target",
container: "#modal",
visible: true
}
}
]
});
console.log(result);
```
```bash cURL theme={"system"}
# Direct form - scroll down 500px
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"scroll": 500
}]
}'
# Direct form - scroll up 200px
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"scroll": -200
}]
}'
# Direct form - scroll to bottom
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"scroll": "bottom"
}]
}'
# Direct form - scroll to element
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"scroll": "#comments"
}]
}'
# Extended form - scroll by pixels
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"scroll": {
"x": 100,
"y": 500
}
}]
}'
# Extended form - scroll to element in container
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"scroll": {
"to": "#target",
"container": "#modal",
"visible": true
}
}]
}'
```
Automatically scroll the page to load dynamic content (infinite scroll). Continuously scrolls until content stops loading or timeout is reached.
**Parameters:**
**Direct form** - Pass boolean or number:
* `auto_scroll: true` - Use default settings
* `auto_scroll: 30000` - Max duration in milliseconds
**Extended form** - Use object with options:
* `max_duration` (optional) - Maximum duration in milliseconds to scroll (number, default: 25000)
* `delay_after_scroll` (optional) - Delay in milliseconds between scroll steps (number, default: 200)
* `step_size` (optional) - Pixels to scroll per step (number, defaults to viewport height)
* `click_selector` (optional) - CSS selector to click before scrolling (string, e.g., "Load More" button)
* `container` (optional) - CSS selector of container element to scroll within (string)
* `idle_timeout` (optional) - Stop scrolling after this many milliseconds of no new content (number, default: 7000)
* `pause_on_selector` (optional) - Pause scrolling if this selector appears above the cursor position (string)
* `required` (optional) - Set to `false` to make this step optional (boolean, default: `true`)
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Direct form - boolean (use defaults)
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"auto_scroll": True # Auto scroll with default settings
}
]
)
# Direct form - number (max duration)
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"auto_scroll": 30000 # Auto scroll for max 30 seconds
}
]
)
# Extended form - with options
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"auto_scroll": {
"max_duration": 30000,
"container": "#feed",
"click_selector": ".load-more",
"delay_after_scroll": 500,
"idle_timeout": 7000
}
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Direct form - boolean (use defaults)
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
auto_scroll: true // Auto scroll with default settings
}
]
});
// Direct form - number (max duration)
const result2 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
auto_scroll: 30000 // Auto scroll for max 30 seconds
}
]
});
// Extended form - with options
const result3 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
auto_scroll: {
max_duration: 30000,
container: "#feed",
click_selector: ".load-more",
delay_after_scroll: 500,
idle_timeout: 7000
}
}
]
});
console.log(result);
```
```bash cURL theme={"system"}
# Direct form - boolean
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"auto_scroll": true
}]
}'
# Direct form - number
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"auto_scroll": 30000
}]
}'
# Extended form - with options
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"auto_scroll": {
"max_duration": 30000,
"container": "#feed",
"click_selector": ".load-more",
"delay_after_scroll": 500,
"idle_timeout": 7000
}
}]
}'
```
Auto scroll continuously scrolls the page until `idle_timeout` milliseconds pass with no new content appearing, or until `max_duration` is reached. Use `click_selector` to handle "Load More" buttons.
Capture a screenshot of the page and return as base64-encoded image.
**Parameters:**
**Direct form** - Pass boolean to capture full page screenshot:
* `screenshot` (required) - Set to `true` to capture full page PNG screenshot
**Extended form** - Use object with options:
* `full_page` (optional) - Capture full scrollable page (boolean, default: `true`)
* `format` (optional) - Image format: `'png'` (default), `'jpeg'`, or `'webp'`
* `quality` (optional) - Image quality for jpeg/webp (number, 0-100, default: 90)
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Direct form - full page PNG screenshot
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"screenshot": True
}
]
)
# Extended form - with options
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"screenshot": {
"full_page": False,
"format": "jpeg",
"quality": 90
}
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Direct form - full page PNG screenshot
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
screenshot: true
}
]
});
// Extended form - with options
const result2 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
screenshot: {
full_page: false,
format: "jpeg",
quality: 90
}
}
]
});
console.log(result);
```
```bash cURL theme={"system"}
# Direct form
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"screenshot": true
}]
}'
# Extended form
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"screenshot": {
"full_page": false,
"format": "jpeg",
"quality": 90
}
}]
}'
```
Retrieve all cookies set in the browser for the current page.
**Parameters:**
**Direct form** - Pass boolean to get all cookies:
* `get_cookies` (required) - Set to `true` to retrieve all cookies
**Extended form** - Use object with options:
* `domain` (optional) - Domain filter for cookies (string, e.g., ".example.com")
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Direct form - get all cookies
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"get_cookies": True
}
]
)
# Extended form - with domain filter
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"get_cookies": {
"domain": ".example.com"
}
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Direct form - get all cookies
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
get_cookies: true
}
]
});
// Extended form - with domain filter
const result2 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
get_cookies: {
domain: ".example.com"
}
}
]
});
console.log(result);
```
```bash cURL theme={"system"}
# Direct form
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"get_cookies": true
}]
}'
# Extended form
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"get_cookies": {
"domain": ".example.com"
}
}]
}'
```
Make HTTP requests from the browser context and return the response.
**Parameters:**
**Direct form** - Pass URL as a string:
* `fetch` (required) - URL for the HTTP request (GET method)
**Extended form** - Use object with options:
* `url` (required) - URL to request (string)
* `method` (optional) - HTTP method: `'GET'` (default), `'POST'`, `'PUT'`, `'DELETE'`, `'PATCH'`, etc.
* `headers` (optional) - HTTP headers to send as key-value object
* `body` (optional) - Request body as string (for POST, PUT, PATCH)
* `timeout` (optional) - Maximum time in milliseconds to wait for response (number, default: 15000)
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Direct form - simple GET request
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"fetch": "https://api.example.com/data" # Simple GET request
}
]
)
# Extended form - POST with headers and body
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"fetch": {
"url": "https://api.example.com/submit",
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"body": '{"key": "value"}',
"timeout": 15000
}
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Direct form - simple GET request
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
fetch: "https://api.example.com/data" // Simple GET request
}
]
});
// Extended form - POST with headers and body
const result2 = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
fetch: {
url: "https://api.example.com/submit",
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: '{"key": "value"}',
timeout: 15000
}
}
]
});
console.log(result);
```
```bash cURL theme={"system"}
# Direct form
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"fetch": "https://api.example.com/data"
}]
}'
# Extended form
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [{
"fetch": {
"url": "https://api.example.com/submit",
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"body": "{\"key\": \"value\"}",
"timeout": 15000
}
}]
}'
```
The first `fetch` in a `browser_actions` is free. Starting from the second request, each additional `fetch` is billed as a VX6 request.
You can chain multiple actions together in the `browser_actions` array. They execute sequentially.
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"fill": {
"selectors": ["input[type='search']"],
"text": "laptop"
}
},
{
"wait": "1s"
},
{
"click": {
"selectors": ["button[type='submit']"]
}
},
{
"wait_for_element": {
"selector": ".results",
"timeout": 5000
}
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from '@nimble-way/nimble-js';
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
fill: {
selectors: ["input[type='search']"],
text: "laptop"
}
},
{
wait: "1s"
},
{
click: {
selectors: ["button[type='submit']"]
}
},
{
wait_for: {
selectors: [".results"],
timeout: "5s"
}
}
]
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [
{
"fill": {
"selectors": ["input[type='\''search'\'']"],
"text": "laptop"
}
},
{
"wait": "1s"
},
{
"click": {
"selectors": ["button[type='\''submit'\'']"]
}
},
{
"wait_for_element": {
"selector": ".results",
"timeout": 5000
}
}
]
}'
```
## Example response
When browser actions complete successfully, you'll receive the final page state along with any data captured.
The response includes:
* **data**: All related extacted data
* **data.html**: Final DOM state after all actions
* **data.screenshot**: Page screenshot if used
* **data.cookies**: Collected cookies if `get_cookies` was used by order
* **data.fetch**: HTTP response if `fetch` was used by order
* **metadata**: Execution details including task id, driver used, execution time and more
* **metadata.browser\_actions**: The browser actions results per step
```json theme={"system"}
{
"url": "https://www.example.com/",
"task_id": "b1fa7943-cba5-4ec2-a88c-4d2d6799c794",
"status": "success",
"data": {
"html": "...",
"screenshot": "base64_encoded_image_data",
"cookies": [
{
"name": "session_id",
"value": "abc123xyz",
"domain": ".example.com",
"path": "/",
"expires": 1735689600,
"httpOnly": true,
"secure": true
}
],
"fetch": [
{
"status": 200,
"duration": 235,
"method": "POST",
"url": "https://api.example.com/submit",
"headers": {},
"body": "..."
}
]
},
"metadata": {
"query_time": "2026-02-08T22:00:36.132Z",
"query_duration": 1877,
"response_parameters": {
"input_url": "https://www.example.com/"
},
"driver": "vx6"
},
"status_code": 200
}
```
## Best practices
### Use required parameter for optional steps
**Make non-critical steps optional:**
```python theme={"system"}
# ✅ Continue even if optional element isn't found
browser_actions = [
{
"click": {
"selectors": [".cookie-banner button"],
"required": False # Don't fail if banner doesn't exist
}
},
{
"click": {
"selectors": [".submit-button"],
"required": True # This is critical
}
}
]
# ❌ Fail entire request if cookie banner isn't found
browser_actions = [
{
"click": {
"selectors": [".cookie-banner button"]
# required defaults to True
}
}
]
```
### Chain actions with appropriate waits
**Add delays between actions:**
```python theme={"system"}
# ✅ Wait for content to load between actions
browser_actions = [
{
"click": {
"selectors": ["button.load-more"]
}
},
{
"wait": "2s" # Wait for new content to load
},
{
"wait_for_element": {
"selector": ".new-content"
}
}
]
# ❌ No wait - may act on stale content
browser_actions = [
{
"click": {
"selectors": ["button.load-more"]
}
},
{
"click": {
"selectors": [".new-content button"] # May not exist yet
}
}
]
```
### Use specific selectors
**Be precise with CSS selectors:**
```python theme={"system"}
# ✅ Specific selector
selector = "button[data-testid='submit-form']"
# ✅ Unique class or ID
selector = "#unique-submit-button"
# ❌ Too generic - may match wrong element
selector = "button"
# ❌ Fragile - breaks with style changes
selector = ".btn.btn-primary.btn-lg.mt-4"
```
### Optimize auto scroll parameters
**Set appropriate scroll limits:**
```python theme={"system"}
# ✅ Controlled scrolling with limits
auto_scroll = {
"max_duration": 10000, # 10 seconds max
"idle_timeout": 3000, # Stop if no change for 3s
"delay_after_scroll": 500, # Wait between scrolls
"click_selector": ".load-more" # Handle load more buttons
}
# ❌ Excessive scrolling - slow and costly
auto_scroll = {
"max_duration": 60000, # 60 seconds - too long
"delay_after_scroll": 100 # Too fast - may miss content
}example
```
# Formats
Source: https://docs.nimbleway.com/nimble-sdk/web-tools/extract/features/formats
Control response format and included data types
Format options control what data types are included in your response. Specify one or more formats to receive HTML, markdown, screenshots, or extracted links alongside your extracted data.
Common uses:
* **Full page content**: Get raw HTML for custom processing
* **Readable text**: Convert pages to clean markdown format
* **Visual records**: Capture screenshots for monitoring or archival
* **Link extraction**: Get all URLs from the page for further crawling
You can combine multiple formats in a single request. All specified formats
will be included in the response.
## Parameters
Choose which types of content you want in your response. You can request multiple formats at once, and each will be included in the result.
**Available formats:**
* `html` - The full HTML source code of the page
* *Best for:* Custom parsing, preserving exact page structure, accessing all DOM elements
* `markdown` - Clean, readable markdown version of the page
* *Best for:* Content analysis, LLM processing, human-readable output
* `screenshot` - Full-page screenshot as base64-encoded PNG
* *Best for:* Visual verification, monitoring, archival, debugging
* *Note:* Automatically enables rendering (VX8/VX10 driver)
**Example:**
```json theme={"system"}
"formats": ["html", "markdown", "screenshot"]
```
## Usage
### HTML format
Request one format type - html (default). **Best for:**
* Custom HTML parsing
* Preserving exact page structure
* Accessing all DOM elements and attributes
* Archival purposes
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url= "https://www.google.com/search?q=nimble",
formats= ["html"] # default
)
# Access HTML content
html_content = result.data.html
print(html_content)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://www.google.com/search?q=nimble",
formats: ["html"], // default
});
// Access HTML content
const htmlContent = result.data.html;
console.log(htmlContent);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.google.com/search?q=nimble",
"formats": ["html"]
}'
```
### Markdown format
Convert the page to clean, readable markdown. **Best for:**
* Clean text extraction
* Content analysis
* LLM processing
* Human-readable output:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url= "https://www.amazon.com/s?k=ironflask",
formats= ["markdown"]
)
# Access markdown content
markdown_content = result.data.markdown
print(markdown_content)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://www.amazon.com/s?k=ironflask",
formats: ["markdown"],
});
// Access markdown content
const markdownContent = result.data.markdown;
console.log(markdownContent);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.amazon.com/s?k=ironflask",
"formats": ["markdown"]
}'
```
### Screenshot format
Capture a full-page screenshot as a base64-encoded PNG image. **Best for:**
* Visual verification and monitoring
* Page archival and documentation
* Comparing page changes over time
Screenshot format automatically enables JavaScript rendering (VX8 or VX10
driver), which may affect pricing. See [Pricing](/nimble-sdk/admin/pricing)
for driver costs.
```python Python theme={"system"}
from nimble_python import Nimble
import base64
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url="https://www.nimbleway.com",
formats=["screenshot"]
)
# Access screenshot (base64-encoded PNG)
screenshot_base64 = result.data.screenshot
# Save to file
with open("screenshot.png", "wb") as f:
f.write(base64.b64decode(screenshot_base64))
print("Screenshot saved to screenshot.png")
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
import fs from "fs";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://www.nimbleway.com",
formats: ["screenshot"],
});
// Access screenshot (base64-encoded PNG)
const screenshotBase64 = result.data.screenshot;
// Save to file
fs.writeFileSync("screenshot.png", Buffer.from(screenshotBase64, "base64"));
console.log("Screenshot saved to screenshot.png");
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.nimbleway.com",
"formats": ["screenshot"]
}'
```
### Multiple formats
Combine multiple formats to get different data representations:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url="https://www.nimbleway.com",
formats=["html", "markdown", "screenshot"]
)
print(result.data.html)
print(result.data.markdown)
print(result.data.screenshot) # base64-encoded PNG
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://www.nimbleway.com",
formats: ["html", "markdown", "screenshot"],
});
console.log(result.data.html);
console.log(result.data.markdown);
console.log(result.data.screenshot); // base64-encoded PNG
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.nimbleway.com",
"formats": ["html", "markdown", "screenshot"]
}'
```
When combining screenshot with other formats, rendering is automatically
enabled for all formats in the request.
## Example response
When formats are specified, all requested data is included in the response. The response includes:
* **data.html**: Raw HTML if requested
* **data.markdown**: Converted markdown if requested
* **data.screenshot**: Base64-encoded PNG if requested
* **data.links**: Array of extracted URLs if requested
* **data.parsing**: Structured data if parsing was used
* **metadata**: Execution details and formats included:
```json theme={"system"}
{
"url": "https://www.example.com/",
"task_id": "b1fa7943-cba5-4ec2-a88c-4d2d6799c794",
"status": "success",
"data": {
"html": "......",
"markdown": "# Article Title\n\nThis is the article content...",
"screenshot": "iVBORw0KGgoAAAANSUhEUgAAA...",
"links": [
"https://www.example.com/about",
"https://www.example.com/contact",
"https://www.example.com/products",
"https://external-site.com"
],
"parsing": {
"title": "Example Article",
"author": "John Doe"
}
},
"metadata": {
"query_time": "2026-02-08T22:00:36.132Z",
"query_duration": 1877,
"response_parameters": {
"input_url": "https://www.example.com/"
},
"driver": "vx6"
},
"status_code": 200
}
```
## Best practices
### Format selection
**Choose formats based on your needs:**
* Use `html` when you need full DOM access
* Use `markdown` for clean text and content analysis
* Use `screenshot` for visual verification
* Use `links` for discovering URLs to crawl
**Avoid unnecessary formats:**
```python theme={"system"}
# ❌ Don't request all formats if you only need one
formats=["html", "markdown"]
# ✅ Request only what you need
formats=["markdown"]
```
### Performance considerations
* Each format adds processing time
* Screenshots require rendering and are slower
* HTML and markdown are faster to generate
* Request only needed formats for optimal performance
# Geo Targeting
Source: https://docs.nimbleway.com/nimble-sdk/web-tools/extract/features/geo-targeting
Built-in residential proxy allowing Geo-targeting options
Geo Targeting routes each request through a proxy exit in a specific region. Use it when content changes by location or language.
Common uses:
* **Localized content**: pricing, availability, shipping, store pages.
* **SEO & market research**: region-specific SERPs and ads.
* **Fewer blocks**: look like a real local user with residential exits.
## Parameters
Make your request appear as if it's coming from a specific country. Perfect for accessing region-specific content like localized prices or availability.
**When to use:**
* E-commerce sites with different prices by country
* Content that varies by region
* Accessing geo-restricted pages
* SEO analysis for different markets
Use ISO Alpha-2 Country Codes i.e. `US`, `DE`, `GB`.\
Use `ALL` for random country selection.
**Example:**
```json theme={"system"}
"country": "GB"
```
For US or CA locations only - specify which state your request should come from.
Use ISO Alpha-2 Country Codes i.e. `NY`, `AZ`, `CA`
**Note:** Only works when `country` is set to `US` or `CA`. Useful for state-specific content like local store inventory or regional pricing.
**Example:**
```json theme={"system"}
"country": "US",
"state": "CA"
```
Target a specific city for hyper-local content. Works best when combined with country (and state for US cities).
**When to use:**
* Local business listings
* City-specific promotions
* Store availability by location
* Hyper-local content
**Examples:** `"new_york"`, `"london"`, `"paris"`
**Example:**
```json theme={"system"}
"country": "US",
"state": "NY",
"city": "new_york"
```
Replace spaces from city names with underscore (e.g,`New York` becomes `new_york`).
Set the browser's preferred language. This changes the `Accept-Language` header and tells websites which language you prefer.
**Most common locales:**
* `en-US` - English (United States)
* `en-GB` - English (United Kingdom)
* `fr-FR` - French (France)
* `de-DE` - German (Germany)
* `es-ES` - Spanish (Spain)
* `ja-JP` - Japanese (Japan)
* `zh-CN` - Chinese (China)
* `pt-BR` - Portuguese (Brazil)
* `auto` - Automatically match the country
**Best practice:** Match your locale to your country (e.g., `fr-FR` with `country: "FR"`) for the most authentic experience.
**Example:**
```json theme={"system"}
"country": "FR",
"locale": "fr-FR"
```
`country`/`state`/`city` geo targeting changes **where** the request comes
from. `locale` changes **which language** the browser prefers.
## Usage
This request exits from **New York** and sets the browser language to **English**.
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url="https://ipinfo.io/json",
country="US",
state="NY",
locale="en-US",
)
print(result.data.html)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract("https://ipinfo.io/json", {
country: "US",
state: "NY",
locale: "en-US",
});
console.log(result.data.html);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://ipinfo.io/json",
"country": "US",
"state": "NY",
"locale": "en-US"
}'
```
## Best practices
### Use geo targeting when content varies by location
Only specify country/state/city when the content differs by location.
```python theme={"system"}
# ✅ Use for location-specific content
result = nimble.extract({
"url": "https://www.example.com/products",
"country": "GB" # Prices and availability vary by country
})
# ❌ Unnecessary for global content
result = nimble.extract({
"url": "https://www.example.com/about",
"country": "DE" # About page is the same everywhere
})
```
### Match locale to target country
Set the locale to match the country for accurate localized content.
```python theme={"system"}
# ✅ Locale matches country
result = nimble.extract({
"url": "https://www.example.com",
"country": "FR",
"locale": "fr-FR"
})
# ✅ Locale auto matching country
result = nimble.extract({
"url": "https://www.example.com",
"country": "FR",
"locale": "auto"
})
# ❌ Locale doesn't match country
result = nimble.extract({
"url": "https://www.example.com",
"country": "FR",
"locale": "en-US" # May not get French content
})
```
### Start with country-level targeting
Use country-level targeting first, then add state/city if needed.
```python theme={"system"}
# ✅ Start simple with country
result = nimble.extract({
"url": "https://www.example.com",
"country": "US"
})
# ✅ Add state if content differs
result = nimble.extract({
"url": "https://www.example.com",
"country": "US",
"state": "NY" # Only if NY shows different content
})
# ❌ Overly specific when not needed
result = nimble.extract({
"url": "https://www.example.com/global-page",
"country": "US",
"state": "NY", # Unnecessary granularity
"city": "new_york"
})
```
# Custom Headers & Cookies
Source: https://docs.nimbleway.com/nimble-sdk/web-tools/extract/features/headers-and-cookies
Send custom headers and cookies to access personalized or authenticated content
Custom headers and cookies enable you to access personalized data, maintain user sessions, and interact with authenticated endpoints. Set headers and cookies in string or object format to mimic real user behavior and retrieve content that requires specific request contexts.
## When to use
Use custom headers and cookies when you need to:
* **Access authenticated content**: Retrieve data behind login walls
* **Maintain sessions**: Preserve user state across requests
* **Mimic real users**: Include user-specific headers for personalized data
* **API authentication**: Send API keys or tokens in headers
* **Regional content**: Set language or region preferences
This is an advanced feature. Misconfigured headers or cookies may trigger
anti-bot detection or cause requests to fail.
## Parameters
Add custom HTTP headers to your request. Useful for authentication, setting custom user agents, or mimicking specific browsers.
**Common use cases:**
* API authentication (API keys, tokens)
* Custom User-Agent strings
* Accept-Language preferences
* Referer headers
* Custom authentication headers
**Format:** Provide headers as key-value pairs in an object.
**Example:**
```json theme={"system"}
"headers": {
"User-Agent": "MyApp/1.0",
"Accept-Language": "en-US,en;q=0.9",
"X-API-Key": "your-api-key"
}
```
The HTTP method to use for the request.
**Supported methods:** `GET`, `POST`, `PUT`, `DELETE`, `PATCH`
**When to use:**
* `GET` - Fetching data (default)
* `POST` - Submitting forms or data
* `PUT` - Updating resources
* `DELETE` - Removing resources
**Note:** When using `POST` or `PUT`, you'll typically also need to include a `body` parameter.
**Example:**
```json theme={"system"}
"method": "POST"
```
The data to send in the request body. Used with POST, PUT, or PATCH requests.
**Format:** Can be an object (auto-converted to JSON) or a string.
**Common uses:**
* Form submissions
* API payloads
* Search queries
* Data uploads
**Example:**
```json theme={"system"}
"method": "POST",
"body": {
"query": "product search",
"filters": ["category:electronics"]
}
```
Send cookies as a simple string, just like they appear in the browser. Separate multiple cookies with semicolons.
**When to use:**
* Quickest way to add cookies
* When you have a cookie string from browser dev tools
* Session IDs and authentication tokens
**Format:** `name1=value1;name2=value2;name3=value3`
**Example:**
```json theme={"system"}
"cookies": "session_id=abc123xyz;user_pref=en_US;logged_in=true"
```
Send cookies as an array of objects for more control. Each cookie can specify its domain.
**When to use:**
* Different cookies for different domains
* More precise cookie control
* Complex cookie setups
**Each cookie object needs:**
* `key` - Cookie name (required)
* `value` - Cookie value (required)
* `domain` - Cookie domain (optional, defaults to request URL domain)
**Example:**
```json theme={"system"}
"cookies": [
{
"key": "session_id",
"value": "abc123xyz",
"domain": "example.com"
},
{
"key": "user_token",
"value": "token456",
"domain": "api.example.com"
}
]
```
Headers and cookies **cannot** be used together. Please do not include
any cookies when sending custom headers.\ \ Just remember that cookies can be
provided in either string format OR array format, but not both at the same
time.
## Usage
### Send custom headers
Include headers as an object:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url= "https://api.example.com/data",
headers= {
"User-Agent": "MyApp/1.0",
"Accept-Language": "en-US,en;q=0.9",
"Some-Extra-Header": "some-extra-header"
}
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://api.example.com/data",
headers: {
"User-Agent": "MyApp/1.0",
"Accept-Language": "en-US,en;q=0.9",
"Some-Extra-Header": "some-extra-header",
},
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://api.example.com/data",
"headers": {
"User-Agent": "MyApp/1.0",
"Accept-Language": "en-US,en;q=0.9",
"Some-Extra-Header": "some-extra-header"
}
}'
```
### POST requests with headers
Send POST requests with custom headers and body:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url= "https://api.example.com/submit",
method= "POST",
headers= {
"Content-Type": "application/json",
"Some-Extra-Header": "some-extra-header"
},
body= {
"query": "product search",
"filters": ["category:electronics"]
}
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://api.example.com/submit",
method: "POST",
headers: {
"Content-Type": "application/json",
"Some-Extra-Header": "some-extra-header",
},
body: {
query: "product search",
filters: ["category:electronics"],
},
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://api.example.com/submit",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Some-Extra-Header": "some-extra-header"
},
"body": {
"query": "product search",
"filters": ["category:electronics"]
}
}'
```
### Send cookies (string format)
Use simple string format for multiple cookies:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url= "https://www.example.com/account",
cookies= "session_id=abc123xyz;user_pref=en_US;logged_in=true"
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://www.example.com/account",
cookies: "session_id=abc123xyz;user_pref=en_US;logged_in=true",
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com/account",
"cookies": "session_id=abc123xyz;user_pref=en_US;logged_in=true"
}'
```
### Send cookies (object format)
Use object format for domain-specific cookies:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url= "https://www.example.com/dashboard",
cookies= [
{
"key": "session_id",
"value": "abc123xyz",
"domain": "example.com"
},
{
"key": "user_token",
"value": "token456",
"domain": "api.example.com"
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://www.example.com/dashboard",
cookies: [
{
key: "session_id",
value: "abc123xyz",
domain: "example.com",
},
{
key: "user_token",
value: "token456",
domain: "api.example.com",
},
],
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com/dashboard",
"cookies": [
{
"key": "session_id",
"value": "abc123xyz",
"domain": "example.com"
},
{
"key": "user_token",
"value": "token456",
"domain": "api.example.com"
}
]
}'
```
### Capture cookies with browser actions and reuse
Use browser actions to interact with a page (like selecting a zip code), capture the resulting cookies, and pass them to subsequent requests:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Step 1: Perform browser actions and capture cookies
initial_result = nimble.extract(
url= "https://www.example.com",
render= True,
browser_actions= [
{
"click": {
"selector": "#location-selector"
}
},
{
"fill": {
"selector": "#zipcode-input",
"text": "90210"
}
},
{
"click": {
"selector": "#submit-location"
}
},
{
"wait": 2000
},
{
"get_cookies": True
}
]
)
# Extract cookies from the response
captured_cookies = initial_result.data.cookies
# Step 2: Use captured cookies in subsequent requests
# Convert cookies array to string format
cookie_string = ";".join([f"{cookie['name']}={cookie['value']}" for cookie in captured_cookies])
result = nimble.extract(
url= "https://www.example.com/products",
cookies= cookie_string
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Step 1: Perform browser actions and capture cookies
const initialResult = await nimble.extract({
url: "https://www.example.com",
render: true,
browser_actions: [
{
click: {
selector: "#location-selector",
},
},
{
fill: {
selector: "#zipcode-input",
text: "90210",
},
},
{
click: {
selector: "#submit-location",
},
},
{
wait: 2000,
},
{
get_cookies: true,
},
],
});
// Extract cookies from the response
const capturedCookies = initialResult.data.cookies;
// Step 2: Use captured cookies in subsequent requests
// Convert cookies array to string format
const cookieString = capturedCookies
.map((cookie) => `${cookie.name}=${cookie.value}`)
.join(";");
const result = await nimble.extract({
url: "https://www.example.com/products",
cookies: cookieString,
});
console.log(result);
```
```bash cURL theme={"system"}
# Step 1: Perform browser actions and capture cookies
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"browser_actions": [
{
"click": {
"selector": "#location-selector"
}
},
{
"fill": {
"selector": "#zipcode-input",
"text": "90210"
}
},
{
"click": {
"selector": "#submit-location"
}
},
{
"wait": 2000
},
{
"get_cookies": true
}
]
}'
# Response will include cookies in data.cookies array:
# {
# "status": "success",
# "data": {
# "html": "...",
# "cookies": [
# {
# "name": "location_zipcode",
# "value": "90210",
# "domain": ".example.com"
# },
# {
# "name": "session_id",
# "value": "abc123xyz",
# "domain": ".example.com"
# }
# ]
# }
# }
# Step 2: Use captured cookies in subsequent requests
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com/products",
"cookies": "location_zipcode=90210;session_id=abc123xyz"
}'
```
This workflow is useful when you need to set user preferences (like location,
language, or filters) via browser interaction, then make multiple faster
requests with the same session state. See [Browser
Actions](/nimble-sdk/web-tools/extract/features/browser-actions) for more
interaction options.
## Important constraints
**Don't mix headers and cookies:**
```python theme={"system"}
# ❌ Don't send both in same request
result = nimble.extract({
"url": "https://www.example.com",
"headers": {"Some-Extra-Header": "some-extra-header"},
"cookies": "session_id=abc" # May cause conflicts
})
# ✅ Use one method
result = nimble.extract({
"url": "https://www.example.com",
"headers": {"Some-Extra-Header": "some-extra-header"}
})
```
**Detection risk:**
* Improper headers may trigger anti-bot detection
* Invalid cookies can cause request failures
* Test thoroughly before production use
* Monitor success rates when using custom headers/cookies
**Header size limits:**
* Total header size: 32 KB
* Individual header: 8 KB
* Cookie header: 4 KB
This is an advanced feature requiring careful configuration. Always test in a
development environment first.
# JavaScript Rendering
Source: https://docs.nimbleway.com/nimble-sdk/web-tools/extract/features/js-rendering
Control browser rendering for dynamic content and JavaScript execution
JavaScript rendering enables full browser execution to capture dynamically loaded content, handle user interactions, and process JavaScript-heavy websites. Control rendering behavior with advanced options for timeout, iframe handling, and load detection.
## When to use
Use JavaScript rendering when you need to:
* **Load dynamic content**: Capture content loaded via AJAX or fetch requests
* **Execute JavaScript**: Process sites that require JS for content display
* **Handle SPAs**: Extract data from Single Page Applications (React, Vue, Angular)
* **Wait for interactions**: Capture DOM state after user actions
* **See final state**: Get the page as users see it, not raw HTML
## Parameters
Turn JavaScript rendering on or off. When enabled, the page loads in a real browser that executes JavaScript, just like when you visit it yourself.
**When to enable:**
* Single Page Applications (React, Vue, Angular)
* Content loaded via AJAX or fetch
* Sites that need JavaScript to display content
* When you need the page as users see it
**When to keep disabled (faster, cheaper):**
* Static HTML pages
* Simple websites without JavaScript
* When raw HTML is sufficient
**Note:** Rendering requires vx8 or vx10. The vx6 driver doesn't support rendering.
**Example:**
```json theme={"system"}
"render": true
```
Fine-tune how the browser waits and loads the page. Only applies when `render: true`.
**Available options:**
* `render_type` - When to consider the page "loaded"
* `load` (default) - Wait for the standard page load event - good for most pages
* `domready` - Stop as soon as HTML is ready, before images load - fastest option
* `idle2` - Wait until only 2 or fewer network requests in the last 500ms - good for dynamic content
* `idle0` - Wait until zero network activity for 500ms - most thorough, slowest
* `timeout` - Maximum wait time in milliseconds (default: 30,000)
* How long to wait before giving up
* `include_iframes` - Whether to load content inside iframes (default: false)
* Enable for embedded videos, widgets, or important iframe content
* `blocked_domains` - List of domains to block during loading
* Great for blocking ads, analytics, or tracking scripts
* Makes pages load faster and cleaner
**Example:**
```json theme={"system"}
"render_options": {
"render_type": "idle0",
"timeout": 60000,
"include_iframes": true,
"blocked_domains": ["google-analytics.com", "doubleclick.net"]
}
```
## Usage
### Enable basic rendering
Set `render: true` to enable JavaScript execution:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url= "https://www.google.com/search?q=nba+allstars+2026",
render= True
)
print(result.data.html)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://www.google.com/search?q=nba+allstars+2026",
render: true,
});
console.log(result.data.html);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.google.com/search?q=nba+allstars+2026",
"render": true
}'
```
When `render: false` (default), the API returns the raw HTML without
JavaScript execution, suitable for static pages.
### Dynamic content loading
Wait for AJAX-loaded content:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Wait for all network activity to stop
result = nimble.extract(
url= "https://www.target.com/deals/all",
render= True,
render_options= {
"render_type": "idle0",
"timeout": 45000
}
)
print(result.data.html)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Wait for all network activity to stop
const result = await nimble.extract({
url: "https://www.target.com/deals/all",
render: true,
render_options: {
render_type: "idle0",
timeout: 45000,
},
});
console.log(result.data.html);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.google.com/search?q=nba+allstars+2026",
"render": true,
"render_options": {
"render_type": "idle0",
"timeout": 45000
}
}'
```
### Iframe content extraction
Include iframe content in extraction:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Include iframe content (e.g., embedded videos, widgets)
result = nimble.extract(
url= "https://www.example.com/page-with-iframes",
render= True,
render_options= {
"include_iframes": True,
"render_type": "load",
"timeout": 40000
}
)
print(result.data.html)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Include iframe content (e.g., embedded videos, widgets)
const result = await nimble.extract({
url: "https://www.example.com/page-with-iframes",
render: true,
render_options: {
include_iframes: true,
render_type: "load",
timeout: 40000,
},
});
console.log(result.data.html);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com/page-with-iframes",
"render": true,
"render_options": {
"include_iframes": true,
"render_type": "load",
"timeout": 40000
}
}'
```
### Block unnecessary resources
Improve performance by blocking ads and tracking:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Block ads, analytics, and tracking domains
result = nimble.extract(
url= "https://www.example.com",
render= True,
render_options= {
"blocked_domains": [
"googletagmanager.com",
"google-analytics.com",
"facebook.com",
"doubleclick.net",
"ads.example.com"
],
"render_type": "idle2",
"timeout": 25000
}
)
print(result.data.html)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Block ads, analytics, and tracking domains
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
render_options: {
blocked_domains: [
"googletagmanager.com",
"google-analytics.com",
"facebook.com",
"doubleclick.net",
"ads.example.com",
],
render_type: "idle2",
timeout: 25000,
},
});
console.log(result.data.html);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.google.com/search?q=nba+allstars+2026",
"render": true,
"render_options": {
"blocked_domains": [
"googletagmanager.com",
"google-analytics.com",
"facebook.com",
"doubleclick.net",
"ads.example.com"
],
"render_type": "idle2",
"timeout": 25000
}
}'
```
### Fast rendering for simple sites
Use DOMContentLoaded for faster responses:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Don't wait for images/styles to load
result = nimble.extract(
url= "https://www.example.com/article",
render= True,
render_options= {
"render_type": "domready",
"timeout": 15000
},
formats= ["markdown"]
)
print(result.data.markdown)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Don't wait for images/styles to load
const result = await nimble.extract({
url: "https://www.example.com/article",
render: true,
render_options: {
render_type: "domready",
timeout: 15000,
},
formats: ["markdown"],
});
console.log(result.data.markdown);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.google.com/search?q=nba+allstars+2026",
"render": true,
"render_options": {
"render_type": "domready",
"timeout": 15000
},
"formats": ["markdown"]
}'
```
### Combining with browser actions
Rendering works seamlessly with browser actions:
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Render page, then perform actions
result = nimble.extract(
url= "https://www.example.com",
render= True,
render_options= {
"render_type": "idle0",
"timeout": 240000
},
browser_actions= [
{
"click": {
"selector": "button.load-more",
"timeout": 5000
}
},
{
"sleep": "2s"
},
{
"auto_scroll": 5000
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
// Render page, then perform actions
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
render_options: {
render_type: "idle0",
timeout: 240000,
},
browser_actions: [
{
click: {
selector: "button.load-more",
timeout: 5000,
},
},
{
sleep: "2s",
},
{
auto_scroll: 5000,
},
],
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.google.com/search?q=nba+allstars+2026",
"render": true,
"render_options": {
"render_type": "idle0",
"timeout": 45000
},
"browser_actions": [
{
"click": {
"selector": "button.load-more",
"timeout": 5000
}
},
{
"sleep": "2s"
},
{
"auto_scroll": 5000
}
]
}'
```
## Best practices
### Choose the right render type
**`Use load for standard pages:`**
```python theme={"system"}
# ✅ Default for most websites
render_options = {
"render_type": "load"
}
```
**`Use domready for speed:`**
```python theme={"system"}
# ✅ When images/styles aren't needed
render_options = {
"render_type": "domready" # Faster response
}
```
**`Use idle2 for dynamic content:`**
```python theme={"system"}
# ✅ For AJAX-heavy pages
render_options = {
"render_type": "idle2", # Wait for most requests to finish
"timeout": 30000
}
```
**`Use idle0 for complete loading:`**
```python theme={"system"}
# ✅ When you need everything loaded
render_options = {
"render_type": "idle0", # Wait for all network activity
"timeout": 60000 # Higher timeout for slow sites
}
```
### Optimize timeout settings
**Set appropriate timeouts:**
```python theme={"system"}
# ❌ Too short - may miss content
render_options = {
"render_type": "idle0",
"timeout": 5000 # Not enough for slow sites
}
# ✅ Balanced timeout
render_options = {
"render_type": "idle0",
"timeout": 30000 # 30 seconds is usually sufficient
}
# ✅ Extended for slow sites
render_options = {
"render_type": "idle0",
"timeout": 60000 # Up to 60 seconds for very slow sites
}
```
### Block unnecessary domains
**Common domains to block:**
```python theme={"system"}
common_blocked_domains = [
# Analytics
"google-analytics.com",
"googletagmanager.com",
"segment.com",
"mixpanel.com",
# Advertising
"doubleclick.net",
"googlesyndication.com",
"adservice.google.com",
# Social media widgets
"facebook.com",
"twitter.com",
"linkedin.com",
# CDN for ads
"ads.example.com",
"tracking.example.com"
]
result = nimble.extract({
"url": "https://www.example.com",
"render": True,
"render_options": {
"blocked_domains": common_blocked_domains
}
})
```
**Benefits of blocking:**
* Faster page loads
* Lower bandwidth usage
* Reduced detection risk
* Cleaner HTML output
### Handle iframes carefully
**Enable only when needed:**
```python theme={"system"}
# ❌ Don't enable iframes unnecessarily
render_options = {
"include_iframes": True # Slower and larger response
}
# ✅ Enable only for specific content
if need_iframe_content:
render_options = {
"include_iframes": True,
"timeout": 45000 # Increase timeout for iframes
}
else:
render_options = {
"include_iframes": False
}
```
### Combine with network capture
Monitor and capture API calls during rendering:
```python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Render page and capture specific API calls
result = nimble.extract(
url= "https://www.example.com",
render= True,
render_options= {
"render_type": "idle0",
"timeout": 30000
},
network_capture= [
{
"method": "GET",
"url": {
"type": "contains",
"value": "/api/products"
}
}
]
)
# Access captured network data
api_responses = result.data.network_capture
print(api_responses)
```
### Performance optimization
**Choose the minimal driver:**
```python theme={"system"}
# ❌ Don't use vx10 when vx8 works
result = nimble.extract({
"url": "https://simple-spa.com",
"driver": "vx10", # Unnecessary stealth features
"render": True
})
# ✅ Use appropriate driver
result = nimble.extract({
"url": "https://simple-spa.com",
"driver": "vx8", # Sufficient for most SPAs
"render": True
})
```
**Monitor execution time:**
```python theme={"system"}
result = nimble.extract({
"url": "https://www.example.com",
"render": True
})
# Check rendering performance
exec_time = result.metadata.query_duration
print(f"Rendering took {exec_time}ms")
# Optimize if too slow
if exec_time > 10000:
print("Consider blocking domains or changing render_type")
```
### When to skip rendering
Use non-rendering (vx6) when:
* **Static content**: HTML already contains all data
* **API endpoints**: Fetching JSON directly
* **High throughput needed**: Rendering is slower
* **Simple pages**: No JavaScript required
* **Cost optimization**: Non-rendering is cheaper
```python theme={"system"}
# ✅ Skip rendering for static pages
result = nimble.extract({
"url": "https://static-site.com/page.html",
"render": False, # or omit (false is default)
})
```
# Network Capture
Source: https://docs.nimbleway.com/nimble-sdk/web-tools/extract/features/network-capture
Capture internal API calls and dynamic data without parsing HTML
Network Capture intercepts internal API calls made during webpage loading, giving you direct access to structured data in JSON format instead of parsing HTML.
Common uses:
* **Dynamic content**: Capture lazy-loaded data and real-time updates.
* **API access**: Interact directly with backend APIs bypassing UI rendering.
* **Performance**: Reduce overhead by accessing machine-readable responses.
* **Accuracy**: Get reliable data directly from API endpoints.
Network Capture requires page rendering to be enabled (`render: true`). For
XHR/AJAX calls that don't need rendering, use the `is_xhr` parameter instead.
## Parameters
Intercept and capture network requests made by the page. Perfect for accessing hidden APIs or getting data directly from backend calls instead of parsing HTML.
**Requirements:** Only works when `render: true`
**Each capture filter is an object with these options:**
* `method` - Filter by HTTP method (GET, POST, PUT, DELETE, etc.)
* Leave empty to capture any method
* `url.type` - How to match URLs
* `exact` - Match the complete URL exactly
* `contains` - Match URLs containing a specific string
* `url.value` - The URL or URL pattern to match
* `resource_type` - Filter by request type (array)
* Options: `xhr`, `fetch`, `stylesheet`, `script`, `document`, `image`
* Example: `["xhr", "fetch"]` to capture only AJAX/fetch requests
* `validation` - Validate response content (default: false)
* Ensures captured responses are valid
* `wait_for_requests_count` - Wait for this many matching requests (default: 0)
* Useful when you know how many API calls to expect
* `wait_for_requests_count_timeout` - How long to wait in seconds (default: 10)
* Timeout for waiting for the expected request count
**Pro tip:** Use `contains` with `/api/` to capture all API calls, or be specific with exact URLs.
**Example (capture specific API):**
```json theme={"system"}
"network_capture": [
{
"method": "GET",
"url": {
"type": "contains",
"value": "/api/products"
},
"resource_type": ["xhr", "fetch"]
}
]
```
**Example (multiple captures):**
```json theme={"system"}
"network_capture": [
{
"url": {
"type": "contains",
"value": "/graphql"
}
},
{
"url": {
"type": "exact",
"value": "https://api.example.com/data"
},
"wait_for_requests_count": 1
}
]
```
## Usage
### Filter by exact URL match
Capture a specific API endpoint by matching the complete URL.
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url="https://www.example.com",
render=True,
network_capture=[
{
"method": "GET",
"url": {
"type": "exact",
"value": "https://www.example.com/api/data"
}
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
network_capture: [
{
method: "GET",
url: {
type: "exact",
value: "https://www.example.com/api/data",
},
},
],
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"network_capture": [
{
"method": "GET",
"url": {
"type": "exact",
"value": "https://www.example.com/api/data"
}
}
]
}'
```
### Filter by URL pattern
Use `contains` to capture requests with URLs matching a pattern. This is useful for capturing file types (like `.css` or `.js`), requests with dynamic URL components, or when you don't know the exact URL.
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url="https://www.example.com",
render=True,
network_capture=[
{
"url": {
"type": "contains",
"value": "/graphql"
}
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
network_capture: [
{
url: {
type: "contains",
value: "/api/",
},
},
],
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"network_capture": [
{
"url": {
"type": "contains",
"value": "/api/"
}
}
]
}'
```
### Filter by resource type
Capture specific types of resources like XHR, Fetch, or Script requests.
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url="https://www.example.com",
render=True,
network_capture=[
{
"method": "GET",
"resource_type": ["xhr", "fetch"]
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
network_capture: [
{
method: "GET",
resource_type: ["xhr", "fetch"],
},
],
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"network_capture": [
{
"method": "GET",
"resource_type": ["xhr", "fetch"]
}
]
}'
```
### Multiple filters
Combine multiple filters to capture different request types in one call.
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url="https://www.example.com",
render=True,
network_capture=[
{
"method": "GET",
"url": {
"type": "exact",
"value": "https://www.example.com/api/resource"
}
},
{
"url": {
"type": "contains",
"value": ".css"
}
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
network_capture: [
{
method: "GET",
url: {
type: "exact",
value: "https://www.example.com/api/resource",
},
},
{
url: {
type: "contains",
value: ".css",
},
},
],
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"network_capture": [
{
"method": "GET",
"url": {
"type": "exact",
"value": "https://www.example.com/api/resource"
}
},
{
"url": {
"type": "contains",
"value": ".css"
}
}
]
}'
```
### Wait for requests
Use `wait_for_requests_count` to ensure you capture a minimum number of network requests. The request duration will be extended until the count is reached or the timeout expires.
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url="https://www.example.com",
render=True,
network_capture=[
{
"method": "GET",
"resource_type": ["xhr", "script"],
"wait_for_requests_count": 3,
"wait_for_requests_count_timeout": 5
}
]
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://www.example.com",
render: true,
network_capture: [
{
method: "GET",
resource_type: ["xhr", "script"],
wait_for_requests_count: 3,
wait_for_requests_count_timeout: 5,
},
],
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"network_capture": [
{
"method": "GET",
"resource_type": ["xhr", "script"],
"wait_for_requests_count": 3,
"wait_for_requests_count_timeout": 5
}
]
}'
```
This configuration will wait up to 5 seconds to capture at least 3 network
requests matching the filter criteria.
## XHR without rendering
For direct API endpoints that don't require page rendering, use `is_xhr` for better performance.
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url="https://api.example.com/endpoint",
is_xhr=True,
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://api.example.com/endpoint",
is_xhr: true,
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://api.example.com/endpoint",
"is_xhr": true
}'
```
`is_xhr` only works when `render` is `false`. It sends XHR-specific headers
and targets the API URL directly.
## Example response
When browser actions complete successfully, you'll receive the final page state along with any data captured.
The response includes:
* **data**: All related extacted data
* **data.html**: Final DOM state after all actions
* **data.network\_capture**: The network capture response by order
* **metadata**: Execution details including task id, driver used, execution time and more
```json theme={"system"}
{
"url": "https://www.example.com/",
"task_id": "b1fa7943-cba5-4ec2-a88c-4d2d6799c794",
"status": "success",
"data": {
"html": "...",
"network_capture": [
{
"filter": {
"method": "GET",
"resource_type": ["xhr", "script"]
},
"result": [
{
"request": {
"resource_type": "script",
"method": "GET",
"url": "https://www.example.com/script/0001.js",
"headers": {}
},
"response": {
"status": 200,
"headers": {},
"body": "..."
}
},
{
"request": {
"resource_type": "xhr",
"method": "GET",
"url": "https://www.example.com/script/0002.js",
"headers": {}
},
"response": {
"status": 200,
"headers": {},
"body": "..."
}
}
]
}
]
},
"metadata": {
"query_time": "2026-02-08T22:00:36.132Z",
"query_duration": 1877,
"response_parameters": {
"input_url": "https://www.example.com/"
},
"driver": "vx6"
},
"status_code": 200
}
```
## Best practices
### Use specific URL patterns
**Be specific with URL matching:**
```python theme={"system"}
# ✅ Specific pattern for API endpoints
network_capture = [
{
"url": {
"type": "contains",
"value": "/api/v1/products"
}
}
]
# ❌ Too broad - captures everything
network_capture = [
{
"url": {
"type": "contains",
"value": "/"
}
}
]
```
### Filter by resource type
**Narrow down to relevant resources:**
```python theme={"system"}
# ✅ Capture only XHR and Fetch requests
network_capture = [
{
"resource_type": ["xhr", "fetch"]
}
]
# ✅ Capture scripts and stylesheets
network_capture = [
{
"resource_type": ["script", "stylesheet"]
}
]
```
### Set appropriate wait counts
**Use wait\_for\_requests\_count for dynamic content:**
```python theme={"system"}
# ✅ Wait for specific number of requests
network_capture = [
{
"method": "GET",
"resource_type": ["xhr"],
"wait_for_requests_count": 3,
"wait_for_requests_count_timeout": 10
}
]
# ❌ No wait - may miss delayed requests
network_capture = [
{
"method": "GET",
"resource_type": ["xhr"]
}
]
```
### Use XHR mode for direct API calls
**Skip rendering when accessing APIs directly:**
```python theme={"system"}
# ✅ Direct API access without rendering
result = nimble.extract({
"url": "https://api.example.com/data",
"is_xhr": True
})
# ❌ Unnecessary rendering for API endpoints
result = nimble.extract({
"url": "https://api.example.com/data",
"render": True,
"network_capture": [...]
})
```
# Parsing Schema
Source: https://docs.nimbleway.com/nimble-sdk/web-tools/extract/features/parsing-schema
Precise data extraction with powerful parser syntax
Parsing Schema gives you full control over data extraction using a comprehensive parser syntax. Define exact data structures for predictable, low-cost extraction from HTML, JSON, XML, and network captures.
Parsers are the complete recipe for processing web content into structured data. They combine:
* selectors - identify elements
* extractors - extract data from elements
* post-processors (optional) - transform the output
# **When to use**
Use parsing schema when you need:
* **Predictable extraction**: Same selectors extract same data every time
* **Full control**: Specify exact selectors paths and data types
* **High volume**: Process large datasets efficiently
Parsers may break when page structure or selectors change. Monitor source
pages and update parsers as needed.
# **Parameters**
**`Must be set to true`** to enable parsing. This tells Nimble you want to extract structured data using the parser you define.
When disabled, you'll just get raw HTML without structured extraction.
**Example:**
```json theme={"system"}
"parse": true
```
Your custom extraction recipe that defines exactly what data to pull from the page and how to structure it.
**Parser structure:**
Each field in your parser is a key-value pair where:
* **Key** - The name of the field in your output (like `"product_name"` or `"price"`)
* **Value** - An object that describes how to extract that field
**Every parser needs:**
1. `type` - What kind of parser to use
* `terminal` - Extract a single value (like one price)
* `terminal_list` - Extract multiple values (like a list of image URLs)
* `schema` - Extract a nested object (like product details)
* `schema_list` - Extract a list of objects (like multiple products)
* `or` - Try multiple strategies, use first one that works
* `and` - Combine multiple extraction strategies
* `const` - Return a fixed value
2. `selector` - How to find the element on the page
* Use CSS selectors (`.product-name`, `#price`, etc.)
* Or XPath, JSON paths for other data types
3. `extractor` - What data to grab from the element
* `text` - The text content
* `attr` - An attribute value (like `href` or `src`)
* `json` - Parse JSON data
* `raw` - The raw HTML
4. `post_processor` (optional) - Transform the data
* Convert to number, format dates, clean text, etc.
**Think of it as:** "Find THIS element, grab THIS data from it, and format it like THIS"
**Simple example:**
```json theme={"system"}
"parser": {
"title": {
"type": "terminal",
"selector": {
"type": "css",
"css_selector": "h1.product-title"
},
"extractor": {
"type": "text"
}
}
}
```
**List example:**
```json theme={"system"}
"parser": {
"images": {
"type": "terminal_list",
"selector": {
"type": "css",
"css_selector": ".product-gallery img"
},
"extractor": {
"type": "attr",
"attr": "src"
}
}
}
```
### Usage
**Example parser structure:**
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url="https://www.example.com/product",
parse=True,
parser={
"product_name": { # key - output field name
"type": "terminal", # parser type
"selector": { # how to find the element
"type": "css",
"css_selector": ".product-title"
},
"extractor": { # what to extract
"type": "text"
}
},
"price": {
"type": "terminal",
"selector": {
"type": "css",
"css_selector": ".price-value"
},
"extractor": {
"type": "text",
"post_processor": { # optional: transform the data
"type": "number"
}
}
}
}
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://www.example.com/product",
parse: true,
parser: {
product_name: {
// key - output field name
type: "terminal", // parser type
selector: {
// how to find the element
type: "css",
css_selector: ".product-title",
},
extractor: {
// what to extract
type: "text",
},
},
price: {
type: "terminal",
selector: {
type: "css",
css_selector: ".price-value",
},
extractor: {
type: "text",
post_processor: {
// optional: transform the data
type: "number",
},
},
},
},
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com/product",
"parse": true,
"parser": {
"product_name": {
"type": "terminal",
"selector": {
"type": "css",
"css_selector": ".product-title"
},
"extractor": {
"type": "text"
}
},
"price": {
"type": "terminal",
"selector": {
"type": "css",
"css_selector": ".price-value"
},
"extractor": {
"type": "text",
"post_processor": {
"type": "number"
}
}
}
}
}'
```
### **Example Output**
```json theme={"system"}
{
"status": "success",
"data": {
"parsing": {
"product_name": "Wireless Headphones",
"price": 79.99
}
}
}
```
## Parser Types
Supported parsing types:
* `terminal` - Returns a single terminal/literal as output.
* `terminal_list` - Returns a list of literals instead of a single literal.
* `schema` - Returns a dictionary/JSON according to its field parsers.
* `schema_list` - Returns a list of dictionaries/JSONs instead of a single dictionary/JSON.
* `or` - Tries a sequence of parsers and returns the result of the first parser that returns a non-null value
* `and` - Runs a sequence of schema parsers and merges their results into a single output. All parsers execute on the same input, and results are combined (first non-null value wins for overlapping keys).
* `const` - Always returns its `value` regardless of the input. Useful for adding static data to your output.
### terminal
* The most basic parser.
```json theme={"system"}
{
"type": "terminal",
"selector": { ... },
"extractor": { ... } // Defaults to raw extractor if not specified
}
```
```json theme={"system"}
{
"type": "terminal",
"selector": {
"type": "css",
"css_selector": ".product-name"
},
"extractor": {
"type": "text"
}
}
```
### terminal\_list
Returns a list of literals instead of a single literal.
```json theme={"system"}
{
"type": "terminal_list",
"selector": { ... },
"extractor": { ... } // Defaults to raw extractor if not specified
}
```
```json theme={"system"}
{
"type": "terminal_list",
"selector": {
"type": "css",
"css_selector": ".product-gallery img"
},
"extractor": {
"type": "attr",
"attr": "src"
}
}
```
### schema
This is the most commonly used parser for structured data extraction.
```json theme={"system"}
{
"type": "schema",
"selector": { ... }, // Optional
"fields": {
"field_name": { /* Parser */ }
}
}
```
```json theme={"system"}
{
"type": "schema",
"selector": {
"type": "css",
"css_selector": ".product-card"
},
"fields": {
"name": {
"type": "terminal",
"selector": {
"type": "css",
"css_selector": ".product-name"
},
"extractor": {
"type": "text"
}
},
"price": {
"type": "terminal",
"selector": {
"type": "css",
"css_selector": ".price"
},
"extractor": {
"type": "text"
}
}
}
}
```
### schema\_list
Returns a list of dictionaries/JSONs instead of a single dictionary/JSON.
```json theme={"system"}
{
"type": "schema_list",
"selector": { ... }, // Optional
"fields": {
"field_name": { /* Parser */ }
}
}
```
The optional `position` attribute adds an index field to each item in the output list.
```json theme={"system"}
{
"type": "schema_list",
"selector": { ... },
"fields": {
"field_name": { /* Parser */ }
},
"position": {
"field_name": "index",
"start_from": 1 // Optional, defaults to 0
}
}
```
```json theme={"system"}
{
"type": "schema_list",
"selector": {
"type": "css",
"css_selector": ".product-item"
},
"fields": {
"name": {
"type": "terminal",
"selector": {
"type": "css",
"css_selector": ".product-name"
},
"extractor": {
"type": "text"
}
},
"price": {
"type": "terminal",
"selector": {
"type": "css",
"css_selector": ".price"
},
"extractor": {
"type": "text"
}
}
}
}
```
### or
Useful for handling variations in page structure.
```json theme={"system"}
{
"type": "or",
"parsers": [
{
/* Parser 1 */
},
{
/* Parser 2 */
},
{
/* Parser 3 */
}
]
}
```
```json theme={"system"}
{
"type": "or",
"parsers": [
{
"type": "terminal",
"selector": {
"type": "css",
"css_selector": ".sale-price"
},
"extractor": {
"type": "text"
}
},
{
"type": "terminal",
"selector": {
"type": "css",
"css_selector": ".regular-price"
},
"extractor": {
"type": "text"
}
}
]
}
```
### and
Runs a sequence of schema parsers and merges their results into a single output. All parsers execute on the same input, and results are combined (first non-null value wins for overlapping keys).
```json theme={"system"}
{
"type": "and",
"parsers": [
{
/* Schema Parser 1 */
},
{
/* Schema Parser 2 */
}
]
}
```
### const
Always returns its `value` regardless of the input. Useful for adding static data to your output.
```json theme={"system"}
{
"type": "const",
"value": "some_value"
}
```
## Parsing Selectors
Selectors identify elements (HTML, JSON, XML, Network) in the input web page. Supported selectors:
* `css` - Selects elements matching a [CSS selector](https://www.w3schools.com/css/css_selectors.asp).
* `xpath` - Enables powerful element selection using [XPath expressions](https://www.w3schools.com/xml/xpath_intro.asp). Particularly useful for XML documents like RSS feeds and sitemaps.
* `json` - Extracts JSON elements from the page. All subsequent selectors and extractors receive JSON instead of HTML.
* `sequence` - Combines multiple selectors in sequence. Useful for chaining different selector types.
* `parent` - Traverses up the DOM tree (for HTML) or context hierarchy (for JSON). Useful when you need to select a parent element after finding a specific child.
* `root` - Returns the original page (document). Often used with JSON selector to access fields like `network_capture`, `url`, or `html`.
### css
Selects elements matching a [CSS selector](https://www.w3schools.com/css/css_selectors.asp).
```json theme={"system"}
{
"type": "css",
"css_selector": "div.price"
}
```
```json theme={"system"}
// Select by class
{ "type": "css", "css_selector": ".product-name" }
// Select by ID
{ "type": "css", "css_selector": "#main-content" }
// Select by attribute
{ "type": "css", "css_selector": "a[data-product-id]" }
// Complex selector
{ "type": "css", "css_selector": "div.product > h2.title" }
```
### xpath
Enables powerful element selection using [XPath expressions](https://www.w3schools.com/xml/xpath_intro.asp). Particularly useful for XML documents like RSS feeds and sitemaps.
```json theme={"system"}
{
"type": "xpath",
"path": "//book[@category='fiction']"
}
```
* `//element` - Select all elements with the given name - `/root/child` -
Select child elements of root - `//element[@attr='value']` - Select by
attribute value - `//element[position()=1]` - Select first element -
`//*[local-name()='element']` - Select ignoring namespaces
```json theme={"system"}
{
"type": "terminal_list",
"selector": {
"type": "xpath",
"path": "//*[local-name()='loc']"
},
"extractor": {
"type": "text"
}
}
```
```json theme={"system"}
{
"type": "sequence",
"sequence": [
{
"type": "xpath",
"path": "//item"
},
{
"type": "xpath",
"path": ".//title"
}
]
}
```
### json
Extracts JSON elements from the page. All subsequent selectors and extractors receive JSON instead of HTML.
```json theme={"system"}
{
"type": "json",
"path": "nested.keys.in.the.json" // jsonpath
}
```
The `coercion_filter` field provides advanced control when dealing with multiple JSON objects. It uses JSONPath expressions to filter specific JSON objects.
```json theme={"system"}
{
"type": "json",
"coercion_filter": "$[1]", // Get the second JSON object
"path": "nested.keys"
}
```
```json theme={"system"}
{
"type": "json",
"coercion_filter": "$[?(@.type=='product')]",
"path": "name"
}
```
```json theme={"system"}
{
"type": "terminal",
"selector": {
"type": "sequence",
"sequence": [
{
"type": "css",
"css_selector": "script[type='application/ld+json']"
},
{
"type": "json",
"path": "$.offers.price"
}
]
},
"extractor": {
"type": "raw"
}
}
```
### sequence
Combines multiple selectors in sequence. Useful for chaining different selector types.
```json theme={"system"}
{
"type": "sequence",
"sequence": [
{
/* Selector 1 */
},
{
/* Selector 2 */
},
{
/* Selector 3 */
}
]
}
```
```json theme={"system"}
{
"type": "sequence",
"sequence": [
{
"type": "css",
"css_selector": "script#product-data"
},
{
"type": "json",
"path": "$.product"
}
]
}
```
### parent
Traverses up the DOM tree (for HTML) or context hierarchy (for JSON). Useful when you need to select a parent element after finding a specific child.
```json theme={"system"}
{
"type": "parent",
"times": 1 // Number of levels to traverse (default: 1)
}
```
```json theme={"system"}
{
"type": "sequence",
"sequence": [
{
"type": "css",
"css_selector": "span.price"
},
{
"type": "parent",
"times": 2
}
]
}
```
### root
Returns the original page (document). Often used with JSON selector to access fields like `network_capture`, `url`, or `html`.
```json theme={"system"}
{
"type": "root"
}
```
```json theme={"system"}
{
"type": "terminal",
"selector": {
"type": "sequence",
"sequence": [
{
"type": "root"
},
{
"type": "json",
"path": "$.url"
}
]
},
"extractor": {
"type": "raw"
}
}
```
```json theme={"system"}
{
"type": "terminal",
"selector": {
"type": "sequence",
"sequence": [
{
"type": "root"
},
{
"type": "json",
"path": "$.network_capture"
}
]
},
"extractor": {
"type": "raw"
}
}
```
## Parsing Extractors
Extractors specify what data to extract from the selected element. Supported extractors:
* `text` - Extracts the text content of the element. Works with both HTML (CSS selectors) and XML (XPath selectors).
* `strip` (optional, boolean) - If it is set to `false`, leading and trailing whitespaces are preserved in the text. Default is `true`.
* `separator` (optional, string) - Specifies a separator string to use when joining text from different child elements. When extracting text from nested HTML elements, this separator will be inserted between text from different elements. If not specified, text from different elements is concatenated without a separator.
* `attr` - Extracts an attribute value from the element. Works with both HTML and XML elements. common attr:
* `href` - Links
* `src` - Images, scripts
* `data-*` - Custom data attributes
* `class` - CSS classes
* `id` - Element IDs
* `json` - Extracts JSON content using JSONPath.
* `raw` - Extracts an element as-is without coercion. JSON stays as JSON, strings stay as strings. Useful for advanced parsing with complex JSON selectors.
If no extractor is specified, the **raw** extractor is used by default.
### text
Extracts the text content of the element. This extractor works with both HTML elements (from CSS selectors) and XML elements (from XPath selectors).
You can use `strip=false` to keep leading and trailing whitespace characters. The default is to remove them.
The text extractor supports both HTML elements (BeautifulSoup Tag) from CSS
selectors and XML elements (lxml Element) from XPath selectors. This allows
you to use the same extractor regardless of whether you're parsing HTML or XML
documents.
**Basic usage:**
```json theme={"system"}
{
"type": "text",
"regex": "string" // Optional (deprecated), will return 1st match
}
```
```json theme={"system"}
{
"type": "text",
"regex": "string", // Optional (deprecated), will return 1st match
"strip": false
}
```
```json theme={"system"}
{
"type": "text",
"regex": "string", // Optional (deprecated), will return 1st match
"separator": " | "
}
```
```json theme={"system"}
{
"type": "terminal",
"selector": {
"type": "xpath",
"path": "//book/title"
},
"extractor": {
"type": "text",
"strip": true
}
}
```
### attr
Extracts an attribute value from the element. Works with both HTML and XML elements. Common attributes: `href` ,`src` ,`data-*` ,`class` , `id`
```json theme={"system"}
{
"type": "attr",
"attr": "href"
}
```
```json theme={"system"}
{
"type": "terminal",
"selector": {
"type": "css",
"css_selector": "img.product-image"
},
"extractor": {
"type": "attr",
"attr": "src"
}
}
```
### json
Extracts JSON content using JSONPath.
```json theme={"system"}
{
"type": "json",
"path": "nested.keys.in.the.json"
}
```
### raw
Extracts an element as-is without coercion. JSON stays as JSON, strings stay as strings. Useful for advanced parsing with complex JSON selectors.
```json theme={"system"}
{
"type": "raw"
}
```
## Parsing Post Processors
Post processors transform extractor output. Define them in the extractor's `post_processor` field. Supported post-procession options:
* `url` - Converts relative URLs to absolute URLs based on the page origin.
* `regex` - Transforms output using a [regular expression](https://regexr.com/). The optional `group` parameter extracts a specific capturing group (defaults to 0).
* `format` - Formats input into a string using Python's str.format, where the input is available as `{data}`.
* `date` - Formats dates to ISO format or custom format.
* `boolean` - Transforms output to boolean based on conditions: `contains`, `exists`, or `regex`. Use `not: true` to reverse the result.
* `number` - Coerces output to a number (int or float). Handles formatted numbers like `"1.5M"` → `1500000` or `"2,100"` → `2100`.
* `country` - Converts country names to country codes.
* `sequence` - Applies multiple post processors in sequence.
### url
Converts relative URLs to absolute URLs based on the page origin.
```json theme={"system"}
{
"extractor": {
"type": "text",
"post_processor": {
"type": "url"
}
}
}
```
* Input: `"/news/article"` - Output: `"https://www.example.com/news/article"`
### regex
Transforms output using a [regular expression](https://regexr.com/). The optional `group` parameter extracts a specific capturing group (defaults to 0).
```json theme={"system"}
{
"extractor": {
"type": "text",
"post_processor": {
"type": "regex",
"regex": "\\d+",
"group": 0 // Optional
}
}
}
```
```json theme={"system"}
{
"extractor": {
"type": "text",
"post_processor": {
"type": "regex",
"regex": "\\d+\\.\\d+"
}
}
}
```
```json theme={"system"}
{
"extractor": {
"type": "text",
"post_processor": {
"type": "regex",
"regex": "Price: (\\d+)\\.(\\d+)",
"group": 1
}
}
}
```
### format
Formats input into a string using Python's str.format, where the input is available as `{data}`.
```json theme={"system"}
{
"extractor": {
"type": "text",
"post_processor": {
"type": "format",
"format": "${data}"
}
}
}
```
- Input: 5.00 - Output: "\$5.00"
### date
Formats dates to ISO format or custom format.
```json theme={"system"}
{
"extractor": {
"type": "text",
"post_processor": {
"type": "date",
"format": "%d/%m/%y" // Optional, defaults to ISO format
}
}
}
```
* Input: `"5 days ago"` - Output (no format): `"2024-07-29T00:00:00"` - Output
(with format `%d/%m/%y`): `"29/07/2024"`
### boolean
Transforms output to boolean based on conditions: `contains`, `exists`, or `regex`. Use `not: true` to reverse the result.
```json theme={"system"}
{
"extractor": {
"type": "text",
"post_processor": {
"type": "boolean",
"condition": "contains",
"contains": "InStock"
}
}
}
```
```json theme={"system"}
{
"extractor": {
"type": "text",
"post_processor": {
"type": "boolean",
"condition": "exists"
}
}
}
```
```json theme={"system"}
{
"extractor": {
"type": "text",
"post_processor": {
"type": "boolean",
"condition": "regex",
"regex": "\\d+"
}
}
}
```
```json theme={"system"}
{
"extractor": {
"type": "text",
"post_processor": {
"type": "boolean",
"condition": "contains",
"contains": "OutOfStock",
"not": true
}
}
}
```
### number
Coerces output to a number (int or float). Handles formatted numbers like `"1.5M"` → `1500000` or `"2,100"` → `2100`.
```json theme={"system"}
{
"extractor": {
"type": "text",
"post_processor": {
"type": "number",
"locale": "en", // Optional: locale for number parsing
"force_type": "float" // Optional: "int" or "float"
}
}
}
```
```json theme={"system"}
{
"extractor": {
"type": "text",
"post_processor": {
"type": "number",
"locale": "de"
}
}
}
```
Input: `"1.000,50"` → Output: `1000.50`
### country
Converts country names to country codes.
```json theme={"system"}
{
"extractor": {
"type": "text",
"post_processor": {
"type": "country"
}
}
}
```
* Input: `"United States"` - Output: `"US"`
### sequence
Applies multiple post processors in sequence.
```json theme={"system"}
{
"extractor": {
"type": "text",
"post_processor": {
"type": "sequence",
"sequence": [
{
"type": "regex",
"regex": "\\d+\\.\\d+"
},
{
"type": "number"
}
]
}
}
}
```
* Input: `"The price is $50.25!"` - After regex: `"50.25"` - After number:
`50.25`
## Complete Examples
### Parsing a BBC News Article
This example demonstrates parsing a complete BBC news article about a three-legged cat, showing how to extract structured data from HTML using various parser types, selectors, and extractors.
**Target URL:** `https://www.bbc.com/news/articles/cervlxymly2o`
**Target Schema:**
```json theme={"system"}
{
"url": "string",
"title": "string",
"date": "string",
"author": {
"name": "string",
"organization": "string"
},
"images": ["string"],
"paragraphs": ["string"]
}
```
### Field-by-Field Breakdown
The URL is the canonical link for the page, typically found in the HTML `head` tag under a `link` element with `rel="canonical"`.
**HTML Structure:**
```html theme={"system"}
```
**Parser:**
```json theme={"system"}
{
"type": "terminal",
"description": "Extracts the canonical URL from the page's head section",
"selector": {
"type": "css",
"css_selector": "link[rel='canonical']"
},
"extractor": {
"type": "attr",
"attr": "href"
}
}
```
**Explanation:**
* **Selector:** `link[rel='canonical']` selects the first link element with `rel="canonical"`
* **Extractor:** `attr` with `href` extracts the URL from the href attribute
The article title is contained in an `h1` element within a headline block.
**HTML Structure:**
```html theme={"system"}
Three-legged cat 'brings town together'
```
**Parser:**
```json theme={"system"}
{
"type": "terminal",
"description": "Main headline of the article",
"selector": {
"type": "css",
"css_selector": "div[data-component='headline-block'] h1"
},
"extractor": {
"type": "text"
}
}
```
**Explanation:**
* **Selector:** `div[data-component='headline-block'] h1` targets the h1 inside the headline block
* **Extractor:** `text` extracts the text content from the element
The publication date is in a `time` element and needs to be formatted to ISO format.
**HTML Structure:**
```html theme={"system"}
```
**Parser:**
```json theme={"system"}
{
"type": "terminal",
"description": "Publication date in ISO format",
"selector": {
"type": "css",
"css_selector": "div[data-testid='byline-new'] time"
},
"extractor": {
"type": "text",
"post_processor": {
"type": "date"
}
}
}
```
**Explanation:**
* **Selector:** `div[data-testid='byline-new'] time` targets the time element
* **Extractor:** `text` with `date` post-processor converts "29 July 2024" to "2024-07-29T00:00:00"
This field requires JavaScript rendering. Add render options to your API request to wait for this element.
The author information contains both name and organization, requiring a nested schema parser.
**HTML Structure:**
```html theme={"system"}
Martin Heath
BBC News, Northamptonshire
```
**Parser:**
```json theme={"system"}
{
"type": "schema",
"description": "Author information with name and organization",
"selector": {
"type": "css",
"css_selector": "div[data-testid='byline-new-contributors']"
},
"fields": {
"name": {
"type": "terminal",
"selector": {
"type": "css",
"css_selector": "span[class]"
},
"extractor": {
"type": "text"
}
},
"organization": {
"type": "terminal",
"selector": {
"type": "css",
"css_selector": "span:not([class])"
},
"extractor": {
"type": "text"
}
}
}
}
```
**Explanation:**
* **Schema Parser:** Returns a nested object with multiple fields
* **Selector Nesting:** Parent selector scopes child selectors to the byline-new-contributors div
* **Name Selector:** `span[class]` selects spans with a class attribute
* **Organization Selector:** `span:not([class])` selects spans without a class attribute
Extract all image URLs from the article, converting relative URLs to absolute.
**HTML Structure:**
```html theme={"system"}
```
**Parser:**
```json theme={"system"}
{
"type": "terminal_list",
"description": "All article images with absolute URLs",
"selector": {
"type": "css",
"css_selector": "article img"
},
"extractor": {
"type": "attr",
"attr": "src",
"post_processor": {
"type": "url"
}
}
}
```
**Explanation:**
* **terminal\_list:** Returns an array of values instead of a single value
* **Selector:** `article img` selects all img elements within article
* **Extractor:** `attr` with `src` gets the image source
* **Post-processor:** `url` converts relative URLs to absolute (e.g., `/news/...` → `https://www.bbc.com/news/...`)
Extract all article paragraphs as an array of strings.
**HTML Structure:**
```html theme={"system"}
A three-legged cat has captured a town's imagination...
The people of Daventry, Northamptonshire, love taking photographs...
```
**Parser:**
```json theme={"system"}
{
"type": "terminal_list",
"description": "Article content paragraphs",
"selector": {
"type": "css",
"css_selector": "article div[data-component='text-block'] p"
},
"extractor": {
"type": "text"
}
}
```
**Explanation:**
* **terminal\_list:** Returns an array of paragraph texts
* **Selector:** `article div[data-component='text-block'] p` selects all p elements in text blocks
* **Extractor:** `text` extracts the text content from each paragraph
### Complete Parser
```json theme={"system"}
{
"type": "schema",
"description": "Parses a BBC news article into structured data",
"fields": {
"url": {
"type": "terminal",
"description": "Canonical URL of the article",
"selector": {
"type": "css",
"css_selector": "link[rel='canonical']"
},
"extractor": {
"type": "attr",
"attr": "href"
}
},
"title": {
"type": "terminal",
"description": "Main headline of the article",
"selector": {
"type": "css",
"css_selector": "div[data-component='headline-block'] h1"
},
"extractor": {
"type": "text"
}
},
"date": {
"type": "terminal",
"description": "Publication date in ISO format",
"selector": {
"type": "css",
"css_selector": "div[data-testid='byline-new'] time"
},
"extractor": {
"type": "text",
"post_processor": {
"type": "date"
}
}
},
"author": {
"type": "schema",
"description": "Author information",
"selector": {
"type": "css",
"css_selector": "div[data-testid='byline-new-contributors']"
},
"fields": {
"name": {
"type": "terminal",
"selector": {
"type": "css",
"css_selector": "span[class]"
},
"extractor": {
"type": "text"
}
},
"organization": {
"type": "terminal",
"selector": {
"type": "css",
"css_selector": "span:not([class])"
},
"extractor": {
"type": "text"
}
}
}
},
"images": {
"type": "terminal_list",
"description": "All article images",
"selector": {
"type": "css",
"css_selector": "article img"
},
"extractor": {
"type": "attr",
"attr": "src",
"post_processor": {
"type": "url"
}
}
},
"paragraphs": {
"type": "terminal_list",
"description": "Article content paragraphs",
"selector": {
"type": "css",
"css_selector": "article div[data-component='text-block'] p"
},
"extractor": {
"type": "text"
}
}
}
}
```
### Example Output
```json theme={"system"}
{
"url": "https://www.bbc.com/news/articles/cervlxymly2o",
"title": "Three-legged cat 'brings town together'",
"date": "2024-07-29T00:00:00",
"author": {
"name": "Martin Heath",
"organization": "BBC News, Northamptonshire"
},
"images": [
"https://ichef.bbci.co.uk/news/480/cpsprodpb/2a87/live/321fae30-4c01-11ef-b2d2-cdb23d5d7c5b.jpg.webp",
"https://ichef.bbci.co.uk/news/480/cpsprodpb/a8c2/live/904194b0-4c01-11ef-b2d2-cdb23d5d7c5b.jpg.webp",
"https://ichef.bbci.co.uk/news/480/cpsprodpb/7579/live/9ecae4f0-4c01-11ef-aebc-6de4d31bf5cd.jpg.webp"
],
"paragraphs": [
"A three-legged cat has captured a town's imagination with his appearances in shops and offices.",
"The people of Daventry, Northamptonshire, love taking photographs of the 14-year-old feline and documenting his travels on social media.",
"Funds have been raised to buy a street sign with his name on it, and souvenir Salem T-shirts could follow."
]
}
```
### API Request Example
```python Python theme={"system"}
from nimble_python import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract(
url="https://www.bbc.com/news/articles/cervlxymly2o",
parse=True,
render=True,
render_flow=[{
"wait_for": {
"selectors": ["div[data-testid='byline-new'] time"]
}
}],
parser={
"type": "schema",
"description": "Parses a BBC news article into structured data",
"fields": {
# ... (full parser structure as shown above)
}
}
)
print(result)
```
```javascript Node theme={"system"}
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: "YOUR-API-KEY" });
const result = await nimble.extract({
url: "https://www.bbc.com/news/articles/cervlxymly2o",
parse: true,
render: true,
render_flow: [
{
wait_for: {
selectors: ["div[data-testid='byline-new'] time"],
},
},
],
parser: {
type: "schema",
description: "Parses a BBC news article into structured data",
fields: {
// ... (full parser structure as shown above)
},
},
});
console.log(result);
```
```bash cURL theme={"system"}
curl -X POST 'https://sdk.nimbleway.com/v1/extract' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.bbc.com/news/articles/cervlxymly2o",
"parse": true,
"render": true,
"render_flow": [{
"wait_for": {
"selectors": ["div[data-testid=\"byline-new\"] time"]
}
}],
"parser": {
"type": "schema",
"description": "Parses a BBC news article into structured data",
"fields": {
...
}
}
}'
```
This parser can be reused for any BBC news article following the same structure - just change the URL!
### Parsing Embedded JSON from Etsy.com Prodcut Page
This example demonstrates parsing structured data from embedded JSON-LD (Linked Data JSON) within an HTML page. Many websites embed JSON-LD in their HTML to help search engines understand their content - we can leverage this for easier, more reliable parsing.
**What is LD+JSON?** Linked Data JSON is a format for structuring data in a machine-readable way. It's often embedded in webpages using `