Scraper apiDeveloper guides

CrewAI

geonode-scraper-crewai builds CrewAI tools you can call with tool.run(...) or attach to an Agent. Each tool returns a JSON-friendly dict.

Responses below are from live runs against https://scraper.geonode.io.

Setup

CrewAI requires Python 3.10 through 3.13.

pip install geonode-scraper-crewai python-dotenv

Create a .env file:

GEONODE_SCRAPER_API_KEY=your_geonode_key
SCRAPER_API_BASE_URL=https://scraper.geonode.io
import os
from dotenv import load_dotenv
from geonode_scraper_crewai import build_crewai_tools
from geonode_scraper_tools_core import ScraperToolSettings

load_dotenv()

settings = ScraperToolSettings(
    host=os.environ.get("SCRAPER_API_BASE_URL", "https://scraper.geonode.io"),
    api_key=os.environ["GEONODE_SCRAPER_API_KEY"],
)

tools = build_crewai_tools(settings=settings)
by_name = {tool.name: tool for tool in tools}

Host

Use https://scraper.geonode.io for production.

Response shape

Every tool returns a dict like:

{
    "ok": True,
    "operation": "extract",
    "attempts": 1,
    "result": { ... },
}

Read the payload from response["result"].

Tools overview

GroupTool names
Extractionscraper_extract_content, scraper_get_job_result, scraper_wait_for_job, scraper_list_jobs
Batchscraper_create_batch, scraper_get_batch_status, scraper_wait_for_batch, scraper_list_batch_jobs
Crawlscraper_create_crawl, scraper_get_crawl_status, scraper_wait_for_crawl, scraper_list_crawl_jobs
Mapscraper_map_urls, scraper_list_map_jobs, scraper_get_map_job
Searchscraper_search, scraper_list_search_jobs, scraper_get_search_job
Accountscraper_get_statistics, scraper_get_concurrency_usage, scraper_check_health

Extraction

scraper_extract_content (sync)

response = by_name["scraper_extract_content"].run(
    url="https://docs.geonode.com/docs/scraper-api/quick-start",
    formats=["markdown"],
    processing_mode="sync",
)

result = response["result"]
markdown = (result.get("data") or {}).get("markdown") or ""
print("ok:", response["ok"])
print("tokens:", result.get("tokens_charged"))
print("markdown_len:", len(markdown))
print("preview:", markdown[:200])

Response (live run):

ok: True
tokens: 1
markdown_len: 15871
preview: ---
canonical: https://docs.geonode.com/docs/scraper-api/quick-start
meta-description: Get your API key, authenticate requests, and choose the right API for your use case.
...

scraper_extract_content (async)

response = by_name["scraper_extract_content"].run(
    url="https://docs.geonode.com/docs/scraper-api/quick-start",
    formats=["markdown"],
    processing_mode="async",
)

result = response["result"]
print("job_id:", result["job_id"])
print("status:", result["status"])

Response (live run):

job_id: e35c4d0e-9df3-43b9-9446-33c517b1cfc4
status: queued

scraper_wait_for_job

response = by_name["scraper_wait_for_job"].run(
    job_id="e35c4d0e-9df3-43b9-9446-33c517b1cfc4",
    timeout_seconds=120,
)

result = response["result"]
markdown = (result.get("data") or {}).get("markdown") or ""
print("status:", result["status"])
print("markdown_len:", len(markdown))
print("poll_attempts:", response.get("poll_attempts"))

Response (live run):

status: completed
markdown_len: 15871
poll_attempts: 4

scraper_get_job_result

response = by_name["scraper_get_job_result"].run(
    job_id="e35c4d0e-9df3-43b9-9446-33c517b1cfc4",
)

result = response["result"]
print("status:", result["status"])
print("tokens:", result.get("tokens_charged"))

Response (live run):

status: completed
tokens: 1

scraper_list_jobs

response = by_name["scraper_list_jobs"].run(page=1, page_size=3)

result = response["result"]
print("page:", result["page"], "page_size:", result["page_size"])
for job in result.get("jobs") or []:
    print(job["job_id"], job["status"], job.get("url"))

Response (live run):

page: 1 page_size: 3
752b8599-5915-441c-bc1f-b9fb0d938f72 completed ...
0bcd424e-b5ab-4b85-9cbd-5b44f7ed433c completed http://example.com/
0dbb126c-4331-4b4b-9d55-0c380ba69ae7 completed http://example.com/

Batch

scraper_create_batch

response = by_name["scraper_create_batch"].run(
    urls=[
        "https://docs.geonode.com/docs/scraper-api/quick-start",
        "https://docs.geonode.com/docs/scraper-api",
    ],
    formats=["markdown"],
)

result = response["result"]
print("job_id:", result["job_id"])
print("accepted_urls:", result["accepted_urls"])
print("status:", result["status"])

Response (live run):

job_id: 037be6d5-06e8-480f-9e22-4eac6cfb2966
accepted_urls: 2
status: queued

scraper_get_batch_status

response = by_name["scraper_get_batch_status"].run(
    job_id="037be6d5-06e8-480f-9e22-4eac6cfb2966",
    page=1,
    page_size=10,
)

result = response["result"]
print(result["status"], result["completed_urls"], "/", result["total_urls"])

Response (live run, mid-job):

processing 0 / 2

scraper_wait_for_batch

response = by_name["scraper_wait_for_batch"].run(
    job_id="037be6d5-06e8-480f-9e22-4eac6cfb2966",
    timeout_seconds=120,
)

result = response["result"]
print(result["status"], result["completed_urls"], "/", result["total_urls"])
print("poll_attempts:", response.get("poll_attempts"))

Response (live run):

completed 2 / 2
poll_attempts: 3

scraper_list_batch_jobs

response = by_name["scraper_list_batch_jobs"].run(page=1, page_size=3)

for job in (response["result"].get("jobs") or []):
    print(
        job["job_id"],
        job["status"],
        job["completed_urls"],
        "/",
        job["accepted_urls"],
    )

Response (live run):

037be6d5-06e8-480f-9e22-4eac6cfb2966 completed 2 / 2
600bb35a-d6fc-4e05-be49-816b8f3ad5d7 completed 2 / 2
55b11790-5c7f-4945-bc13-bd9a365a1835 completed 2 / 2

Crawl

scraper_create_crawl

response = by_name["scraper_create_crawl"].run(
    url="https://docs.geonode.com/docs/scraper-api",
    depth=2,
    limit=3,
    formats=["markdown"],
    same_domain_only=True,
)

result = response["result"]
print("job_id:", result["job_id"])
print("estimated_pages:", result["estimated_pages"])
print("status:", result["status"])

Response (live run):

job_id: dbc0fa1a-1fea-496c-abe4-a33c2b91efb7
estimated_pages: 3
status: queued

scraper_get_crawl_status

response = by_name["scraper_get_crawl_status"].run(
    job_id="dbc0fa1a-1fea-496c-abe4-a33c2b91efb7",
    page=1,
    page_size=10,
)

result = response["result"]
print(
    result["status"],
    result.get("completed_pages"),
    "/",
    result.get("total_pages"),
)

Response (live run, early poll):

processing 0 / 1

scraper_wait_for_crawl

response = by_name["scraper_wait_for_crawl"].run(
    job_id="dbc0fa1a-1fea-496c-abe4-a33c2b91efb7",
    timeout_seconds=180,
)

result = response["result"]
print(result["status"], result["completed_pages"], "/", result["total_pages"])
print("poll_attempts:", response.get("poll_attempts"))

Response (live run):

completed 3 / 3
poll_attempts: 4

scraper_list_crawl_jobs

response = by_name["scraper_list_crawl_jobs"].run(page=1, page_size=2)

for job in (response["result"].get("jobs") or []):
    print(
        job["job_id"],
        job["status"],
        job["completed_pages"],
        "/",
        job["total_pages"],
    )

Response (live run):

dbc0fa1a-1fea-496c-abe4-a33c2b91efb7 completed 3 / 3
ab83f113-5086-46d3-a045-3a42263b5c87 completed 3 / 3

Map

scraper_map_urls

response = by_name["scraper_map_urls"].run(
    url="https://docs.geonode.com/docs/scraper-api",
)

result = response["result"]
links = result.get("links") or []
print("link_count:", result.get("links_count") or len(links))
for link in links[:5]:
    print(link.get("source"), link.get("url"))

Response (live run):

link_count: 112
sitemap https://docs.geonode.com/docs/scraper-api
sitemap https://docs.geonode.com/docs/scraper-api/quick-start
sitemap https://docs.geonode.com/docs/scraper-api/additional-resources/choosing_scraper_api_plan
sitemap https://docs.geonode.com/docs/scraper-api/additional-resources/faq
sitemap https://docs.geonode.com/docs/scraper-api/additional-resources/pricing-and-requests

scraper_list_map_jobs

response = by_name["scraper_list_map_jobs"].run(page=1, page_size=2)

for job in (response["result"].get("jobs") or []):
    print(job["job_id"], job["status"], job.get("links_count"), job.get("url"))

Response (live run):

88b13fab-8d1b-421d-aa0e-256dd705b3aa completed 112 https://docs.geonode.com/docs/scraper-api
3abfc672-2aff-4daf-9f68-f033978ddfbd completed 112 https://docs.geonode.com/docs/scraper-api

scraper_get_map_job

response = by_name["scraper_get_map_job"].run(
    job_id="88b13fab-8d1b-421d-aa0e-256dd705b3aa",
)

result = response["result"]
print("status:", result["status"])
print("link_count:", result.get("links_count"))
for link in (result.get("links") or [])[:3]:
    print(link.get("source"), link.get("url"))

Response (live run):

status: completed
link_count: 112
sitemap https://docs.geonode.com/docs/scraper-api
sitemap https://docs.geonode.com/docs/scraper-api/quick-start
sitemap https://docs.geonode.com/docs/scraper-api/additional-resources/choosing_scraper_api_plan

response = by_name["scraper_search"].run(query="geonode scraper api")

result = response["result"]
print("job_id:", result["job_id"])
print("hit_count:", result.get("results_count") or len(result.get("results") or []))
for hit in (result.get("results") or [])[:5]:
    print(hit["position"], hit["title"], hit["url"])

Response (live run):

job_id: 7eeb9599-c39a-4eba-8e0d-2eaed5a8deab
hit_count: 15
1 Wholesale proxies & web data infrastructure | Geonode https://geonode.com/
2 Geonode - PyPI https://pypi.org/user/Geonode/
3 pavel.s - PyPI https://pypi.org/user/pavel.s/
4 Geonode Documentation | Geonode https://docs.geonode.com/
5 GeoNode https://geonode.org/

scraper_list_search_jobs

response = by_name["scraper_list_search_jobs"].run(page=1, page_size=2)

for job in (response["result"].get("jobs") or []):
    print(job["job_id"], job.get("query"), job["status"], job.get("results_count"))

Response (live run):

7eeb9599-c39a-4eba-8e0d-2eaed5a8deab geonode scraper api completed 15
f80269e1-1911-4fd4-b1a1-fc0f7bbae7f9 geonode scraper api completed 15

scraper_get_search_job

response = by_name["scraper_get_search_job"].run(
    job_id="7eeb9599-c39a-4eba-8e0d-2eaed5a8deab",
)

result = response["result"]
print("status:", result["status"])
print("hit_count:", result.get("results_count"))
for hit in (result.get("results") or [])[:3]:
    print(hit["position"], hit["title"], hit["url"])

Response (live run):

status: completed
hit_count: 15
1 Wholesale proxies & web data infrastructure | Geonode https://geonode.com/
2 Geonode - PyPI https://pypi.org/user/Geonode/
3 pavel.s - PyPI https://pypi.org/user/pavel.s/

Statistics, usage, and health

scraper_get_statistics

response = by_name["scraper_get_statistics"].run()

result = response["result"]
print("extraction_count:", result.get("extraction_count"))
print("success_rate:", result.get("success_rate"))

Response (live run):

extraction_count: 4401
success_rate: 0.95137

scraper_get_concurrency_usage

response = by_name["scraper_get_concurrency_usage"].run()

result = response["result"]
print(
    result["work_concurrency_in_use"],
    "/",
    result["work_concurrency_limit"],
)

Response (live run):

0 / 50

scraper_check_health

response = by_name["scraper_check_health"].run()

result = response["result"]
print(result.get("service"), result.get("status"), result.get("version"))

Response (live run):

Scraper API ok 0.1.0

Selecting a subset of tools

tools = build_crewai_tools(
    settings=settings,
    operations=["extract", "map_urls", "create_crawl", "wait_for_crawl"],
)

print([tool.name for tool in tools])

Response (live run):

['scraper_extract_content', 'scraper_map_urls', 'scraper_create_crawl', 'scraper_wait_for_crawl']

Use tools with an Agent

Attach the tools to a CrewAI agent:

from crewai import Agent
from geonode_scraper_crewai import build_crewai_tools
from geonode_scraper_tools_core import ScraperToolSettings

settings = ScraperToolSettings(
    host="https://scraper.geonode.io",
    api_key=os.environ["GEONODE_SCRAPER_API_KEY"],
)

agent = Agent(
    role="Web Researcher",
    goal="Extract and inspect web content.",
    backstory="Focused on pulling structured data from URLs.",
    tools=build_crewai_tools(settings=settings),
)

The agent can call the same tools shown above. Direct checks still use tool.run(...).


Toolkit helper

from geonode_scraper_crewai import ScraperCrewAIToolkit
from geonode_scraper_tools_core import ScraperToolSettings

settings = ScraperToolSettings(
    host="https://scraper.geonode.io",
    api_key=os.environ["GEONODE_SCRAPER_API_KEY"],
)

toolkit = ScraperCrewAIToolkit.from_settings(settings)
tools = toolkit.get_tools()

For package versions and changelog, see geonode-scraper-crewai on PyPI.

On this page