Skip to main content

langchain-hydrafetch

PyPI CI Python

LangChain integration for the Hydrafetch web data API.

Load pages as documents, search the web as a retriever, and give agents four tools that read, extract and enrich from the live web. Sync and async, fully typed.

Installation

pip install langchain-hydrafetch

Create a key at app.hydrafetch.com and set it:

export HYDRAFETCH_API_KEY="hf_..."

Everything below reads that variable when no api_key= is passed.

Quick start

from langchain_hydrafetch import HydrafetchLoader

docs = HydrafetchLoader("https://example.com/article").load()
print(docs[0].page_content)
print(docs[0].metadata["title"])

Document loader

Three modes. scrape loads one page, crawl walks a site and loads every page it finds, and map returns one document per discovered URL without fetching the bodies.

HydrafetchLoader("https://example.com/article").load()
HydrafetchLoader("https://example.com", mode="crawl", params={"limit": 50}).load()
HydrafetchLoader("https://example.com", mode="map").load()

content_format chooses what lands in page_contentmarkdown by default, or html, rawHtml, summary. params is forwarded to the API untouched, so anything the endpoint accepts works here:

HydrafetchLoader(
    "https://example.com/article",
    content_format="markdown",
    params={"onlyMainContent": True, "preferStructure": True, "blockAds": True},
).load()

Documents carry source and status, plus whatever page metadata was found: title, description, language, site_name, author, published_time, word_count, page_type, image. A redirect adds final_url; a crawled page adds depth; a mapped URL adds lastmod when the sitemap declares one.

Use lazy_load() to stream a large crawl instead of building the whole list in memory:

for doc in HydrafetchLoader("https://example.com", mode="crawl").lazy_load():
    index.add(doc)

Error pages are refused, not loaded

A URL that answers with an error status raises instead of returning a document, because the body of a 404 page is not the page you asked for and a retrieval index should not quietly absorb one.

HydrafetchLoader("https://example.com/gone").load()
# ValueError: https://example.com/gone returned HTTP 404. The body of an error
# page is not the page you asked for; pass raise_for_status=False to load it anyway.

In crawl mode a single dead page must not throw away the whole job, so error pages are dropped and the rest of the crawl is kept. Pass raise_for_status=False to load error pages in either mode.

Retriever

from langchain_hydrafetch import HydrafetchSearchRetriever

retriever = HydrafetchSearchRetriever(k=5)
docs = retriever.invoke("best open source vector databases")

Each document holds the result snippet, with source, title and rank in metadata. Pass scrape_content=True to fetch and return the full page body for every result instead:

HydrafetchSearchRetriever(k=3, scrape_content=True).invoke("...")

That costs one extra credit per result. k works as a constructor argument or per call, and search_params is forwarded to the search endpoint:

retriever.invoke("...", k=2)
HydrafetchSearchRetriever(search_params={"country": "us"})

Agent tools

from langchain_hydrafetch import (
    HydrafetchBrandTool,
    HydrafetchExtractTool,
    HydrafetchScrapeTool,
    HydrafetchSearchTool,
)

tools = [
    HydrafetchSearchTool(),
    HydrafetchScrapeTool(),
    HydrafetchExtractTool(),
    HydrafetchBrandTool(),
]
tool argument returns
hydrafetch_search query, limit JSON with query and results of title, url, snippet
hydrafetch_scrape url the page as markdown
hydrafetch_extract urls, json_schema or prompt JSON with one entry per URL
hydrafetch_brand domain JSON brand record: name, description, tagline, logo assets, colours, fonts, socials

Search finds pages, scrape reads a page you already have. Giving an agent both is the usual setup.

Structured extraction takes either a schema or a plain-language description:

HydrafetchExtractTool().invoke({
    "urls": ["https://example.com/pricing"],
    "json_schema": {
        "type": "object",
        "properties": {"plans": {"type": "array", "items": {"type": "string"}}},
    },
})

HydrafetchExtractTool().invoke({
    "urls": ["https://example.com/about"],
    "prompt": "the founding year and the headquarters city",
})

Async

The retriever and every tool support ainvoke, and the loader supports alazy_load and aload:

docs = await HydrafetchSearchRetriever().ainvoke("...")
text = await HydrafetchScrapeTool().ainvoke({"url": "https://example.com"})

Error handling

Failures raise HydrafetchError from the underlying client, carrying the API's error code, HTTP status and request id.

from hydrafetch import HydrafetchError, HydrafetchTimeout

try:
    docs = HydrafetchLoader(url).load()
except HydrafetchTimeout:
    raise
except HydrafetchError as err:
    if err.is_out_of_credits:
        top_up()
    elif err.is_retryable:
        enqueue(url)
    else:
        raise
Status Meaning Retried
400, 422 invalid request no
401, 403 invalid or missing key no
402 out of credits no
429 rate limited yes, twice with backoff
5xx upstream failure yes, twice with backoff

A page that loads but answers with an error status raises ValueError from the loader instead — that is a bad URL, not a failed request.

Configuration

Every class accepts the same connection options, all optional:

option default meaning
api_key HYDRAFETCH_API_KEY your API key
base_url https://api.hydrafetch.com API base URL
timeout 120.0 per-request timeout in seconds
max_retries 2 retries on 429 and 5xx

Credits

call credits
loader, scrape mode 1
loader, map mode 1
loader, crawl mode 1 per page
retriever 1, plus 1 per result with scrape_content=True
hydrafetch_scrape 1
hydrafetch_search 1
hydrafetch_extract 5 per URL
hydrafetch_brand 5

Failed requests are not billed. Pricing does not vary with page difficulty, so there is no render, stealth or proxy option to set.

Implementation notes

  • Prefer map then a batch of scrape loads over a broad crawl. Fetching a whole site and discarding most of it is the most common source of wasted credits.
  • params in crawl mode is forwarded to the crawl endpoint, so per-page options belong under scrapeOptions. At the top level they are ignored.
  • preferStructure is off by default. Turn it on when headings, lists and tables matter; leave it off for raw article text.
  • The loader constructs its client eagerly, so a missing API key fails at construction rather than at load().
  • The retriever and tools construct their clients lazily on first use, which keeps them cheap to build and safe to define at import time.
  • Metadata keys are snake_cased on the way out, so the API's siteName becomes site_name.
  • Scraped content is untrusted input. Do not pass it to a model as instructions, and keep metadata["source"] with anything extracted from it.

Development

uv sync
uv run ruff check src tests
uv run ruff format --check src tests
uv run pytest -q

Unit tests run offline against fake clients. The integration tests are LangChain's own langchain-tests standard suite; they are skipped unless HYDRAFETCH_API_KEY is set, and they spend real credits.

Links

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

langchain_hydrafetch-0.1.0.tar.gz (155.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

langchain_hydrafetch-0.1.0-py3-none-any.whl (11.5 kB view details)

Uploaded Python 3

File details

Details for the file langchain_hydrafetch-0.1.0.tar.gz.

File metadata

  • Download URL: langchain_hydrafetch-0.1.0.tar.gz
  • Upload date:
  • Size: 155.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for langchain_hydrafetch-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e9eb47d3166a5e8d086c4616c568db7ec35d34e69e35ef656b2c752a1a607bd3
MD5 182cee02a814245d812b78553478ba88
BLAKE2b-256 e416ba7ff1977139f736d6766a6c266120502157c34e4f483fcad32d593115d3

See more details on using hashes here.

Provenance

The following attestation bundles were made for langchain_hydrafetch-0.1.0.tar.gz:

Publisher: publish.yml on Hydrafetch/langchain-hydrafetch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file langchain_hydrafetch-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for langchain_hydrafetch-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0e7407405f3df5bb8f2eada50c93c4d19dc5ac6c8b824c6c343e160815b4f4be
MD5 8be1a0856f51c96482e9fcc05171818b
BLAKE2b-256 bf3d862f6514e538c84a7df9eff7d6f8f07abc93223ee9b189a6b282edb33221

See more details on using hashes here.

Provenance

The following attestation bundles were made for langchain_hydrafetch-0.1.0-py3-none-any.whl:

Publisher: publish.yml on Hydrafetch/langchain-hydrafetch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page