
ZooData
The data layer for AI agents
833 followers
The data layer for AI agents
833 followers
ZooData turns any URL into agent-ready JSON, so AI agents can work with structured data instead of raw HTML or bloated markdown. Use ~75% fewer LLM tokens, pay only for the fields you use, and skip extra extraction credits.Beyond extraction, ZooData gives agents pre-analyzed e-commerce intelligence — competitor, market, traffic, and consumer insights — live for Amazon and TikTok. API, CLI, and MCP server included. Start with 1,000 free credits, no card required.





ZooClaw
Hi PH 👋,
I'm Ning from ZooData.
Quick context on why we built this.
If you've built anything with agents, you know the data problem. You scrape a page — with browser-use, Playwright, whatever — and what comes back is raw HTML or "clean" markdown. Either way it's stuffed with nav bars, footers, ads, and boilerplate. For a human reading it, fine. For an LLM, you're burning thousands of tokens on stuff the model has to filter out before it can do anything useful. At scale that's real money, and most of it is waste.
Markdown is the usual fix. But markdown was built for humans to read, not for an agent that has to act on the data. Different reader, different format — an agent doesn't need prose, it needs structure.
ZooData does the extraction step right:
Any URL → structured JSON. No schema to define, no per-site parsers, no selector glue to maintain.
~75% fewer tokens than raw markdown on the same page — roughly 1/5 the cost of other extractors. And you only pay for the fields you actually use; the extraction itself doesn't burn credits.
API, CLI, and MCP server, so it drops into your agent stack without rewriting anything.
Pre-analyzed e-commerce platform intelligence — competitor, market, traffic, and consumer signals your agent can query directly, instead of scraping and stitching it together itself. More platforms coming.
We believe the next bottleneck for AI agents won't be how smart the models get — it will be the quality of the data they rely on.
As AI-generated content floods the web, agents need data that's clean, structured, and verifiable to make reliable decisions. That's the layer we're building, and it compounds: every page we process makes the next request cheaper, faster, and more trustworthy.
ZooData is the foundation the rest of it runs on — we launched ZooClaw (agents for individuals) here not long ago, and ZooWork (the enterprise version) is coming soon.
1,000 free credits, no card. Just tell your agent:
and you're off.
Would love your feedback. And I'm curious — what's the messiest site you've ever had to scrape? 🙏
@ninghu For teams using agents today, what’s the single biggest pain you still face with web data quality and how would a perfect extractor make your life easier?
ZooData
@ninghu @swati_paliwal Great question. Running agents on web data ourselves every day, the deepest lesson was: missing data isn't the scary part — data that "looks about right" is. A human double-takes at a weird price; an agent just acts on it, and one wrong field flows quietly down the pipeline until you catch it three steps too late.
So we hard-wired one line into extraction: a value either genuinely exists in the page and gets pulled out, or it's null — there is no pathway in the system for "making up a value to fill the slot." Extraction is deterministic: the same page content always yields the same result — if the output changes, it's because the page actually changed, not because the extractor "read" it differently this time. A redesign can break extraction — but breakage shows up as a loud, unbilled failure, never as a quietly wrong value handed back to you.
As for a perfect extractor? I think it would have to know, on its own, that a value might be wrong. That's exactly one of the areas we invest in most — the validation and quality-detection machinery is already running in production, and it keeps evolving release by release. Still short of "perfect," but we're well past the starting line on that road.
What about your team — stale data, misplaced fields, or the holes left by blocked fetches: which burns you most?
@ninghu This is a real pain point. HTML to markdown sounds clean until you realize the model is still reading cookie banners, nav links, footer junk, and six versions of the same product title
The no schema JSON angle is interesting. I’d be curious how ZooData handles pages where the useful data is ambiguous, like marketplaces with sponsored listings, variant pricing, hidden pagination, or content that only appears after interaction. The messiest scraping targets are usually the ones that look simple until every page has a slightly different idea of what a “product” is.
ZooData
@ninghu @vahid_davoudi That's a professional list — one by one:
Sponsored listings: on the e-commerce intelligence side, organic-vs-sponsored is a typed distinction — organic results and the various sponsored placements are labeled separately in the data, so ads never blend into organic data masquerading as market signal.
Variant pricing: variants are first-class — each carries its own SKU, options, price, and availability; there's no "one product, one price" assumption. And when a page displays a price that's inherently ambiguous (an asterisked promo like "$1*"), that raw state is exactly what we return — ambiguity is preserved verbatim, never flattened by a guess.
Hidden pagination: listing extractions carry a next_url field — the next-page (or "load more") link is extracted as data and handed to your agent. Whether and how deep to page is its decision, each call flat-priced — depth belongs to you, not to a black box of ours. Interaction-gated content goes through the interactive variant: an explicit action sequence (click / scroll / wait), executed before extraction.
As for "every page has its own idea of what a product is" — exactly, and that's our whole philosophy: structure what's unambiguous; preserve genuine ambiguity verbatim for you to judge; degrade honestly when a page defeats the type (absent fields, never invented values). Ambiguity is a property of the page — our job is to relay it faithfully, not to pretend it isn't there.
@ninghu @kyle_dong Thanks Kyle, this is a strong answer. I really like the philosophy of preserving ambiguity instead of hiding it behind guessed fields.The next_url approach and explicit action sequence for interaction-gated content also make sense. That feels much more useful for agents than pretending messy pages are clean.
ZooData
@ninghu @vahid_davoudi Thanks! The principle in one line: messiness belongs to the page; honesty belongs to the API. Put it to the test — and if you find an exception, you know where we are.
@ninghu The URL to JSON layer is exactly where a lot of agent workflows get fragile. One thing I would want to see is field provenance: for each extracted field, can the agent trace it back to the source snippet or timestamp before acting on it? Token savings matter, but trust gets much easier when the structured value is reviewable.
ZooData
@ninghu @kevinzrzgg "Trust gets easier than tokens get cheaper" — we fully agree with that ordering. Splitting your two asks:
Timestamp — exists today, and it's stronger than it looks. The realtime endpoints do uncached, on-the-spot collection, so the response's timestamp is the observation moment — there's no "when was this actually fetched" question, because the answer is always "the moment you called." The analytics layer is explicitly labeled as a daily cycle. Freshness here is a labeled property of each endpoint, never a guess.
Reviewability — today it's whole-document, not per-field pointers. Formats are composable: request json and markdown (or rawHtml) in the same call, and every structured value can be checked against the page's own content — if the agent wants to review before acting, the raw material is in the same response, at the same flat price. That's today's trust shape: document-level provenance.
As for per-field source pointers (which snippet a value came from) — plainly: not exposed today. But extraction is deterministic, so every value already has a concrete origin inside the system — exposing it per field is engineering, not research, and it's exactly where our quality work is invested. Your ask is noted.
The data-quality point is the right one, most agent tools skip straight past it to the model.
One thing I'd add from the support side, where we build agents. Clean JSON fixes the token cost, but it quietly adds a different risk. Raw HTML looks messy so you distrust it. A structured field looks authoritative even when the extractor grabbed the wrong element, or the value went stale between the scrape and the moment the agent acts on it. For an agent that only reads, fine. For one that acts on the field, answers a customer or changes a price, a confidently wrong value is worse than a missing one, because nothing tells it to stop.
So the question, does ZooData give the agent anything per field, a confidence score or a freshness timestamp, or is it flat JSON it has to trust fully? On live Amazon/TikTok data I'd expect the real failures to sit there, not in the extraction.
ZooData
@jernej_jan_kocica Good question — and you've split it into the two failures that actually matter: extraction correctness (did we grab the right element) and freshness (has it gone stale before the agent acts). Let me take both honestly.
Confidence (extraction side): no, we don't expose a per-field confidence score today — it's on the roadmap. And your framing is exactly the spec for it: for an acting agent, "a confidently wrong value with nothing telling it to stop" is the failure worth engineering against. A missing value fails safe; a wrong one doesn't. That's the signal we want to give the agent.
Freshness (the side you'd bet the real failures sit on): this is the part we've actually designed hard around, so I can be concrete —
scrape/realtime endpoints force a live fetch on every call. No cache, ever. There's no gap between capture and read — the value is fresh at the moment the agent asks.
analytics/commerce endpoints run on a daily cycle, so every value is explicitly time-bounded rather than pretending to be real-time — the agent knows exactly how old it is.
So interestingly, the live Amazon/TikTok data you flagged as the danger zone is the part we deliberately don't cache — the open gap you've correctly found is extraction-confidence, not staleness. Since you build support agents that act on fields, I'd genuinely like to design that confidence signal with input from your seat rather than guess at it. Happy to swap notes.
@kyle_dong Fair. If freshness is a live fetch with no cache, then that gap is smaller than I guessed. Good.
On the confidence signal, one thing from acting on this data every day. A 0-1 score is the obvious shape but it's the wrong one for an agent that acts, a number gets rubber-stamped, 0.82 means nothing at the moment it has to decide. What you actually want is closer to a boolean per field: was this value read from a labeled source (a data attribute, schema.org, an obvious price node), or was it inferred because something looked like a price. Sourced, act on it. Inferred, never act, only surface for a human. The dangerous field is always the inferred one that came out looking clean.
And keep it per field, not per page. The same page can have a solid title and a guessed price, one score for the whole extraction hides exactly the field that will bite.
Happy to swap notes on it.
ZooData
@jernej_jan_kocica This one's getting framed — you've just articulated the right shape for the confidence problem. Fully agree: a float invites a threshold; a source boolean invites a decision. The destiny of every 0.82 is to become > 0.8 → pass on day one and never be looked at again.
Your sourced/inferred split happens to run with the grain of our architecture: because extraction is deterministic, every value has a concrete origin in the page — which node, what kind of labeling it was read from, is knowable inside the system. Exposing that origin per field is an engineering problem, not a research problem — it's exactly where our quality work is heading, and your comment describes the API shape more crisply than our internal notes do.
On per-field vs per-page — that's already how we behave: on the same page, the title can come back as a clean string while the price, if the page itself doesn't show a clean number ("Free", "Contact for price", an asterisked promo), comes back as the page's own text — or null if it can't be read at all. Each field degrades on its own: one suspect field doesn't sink the page, and a good-looking page doesn't cover for the field that's off.
Taking you up on "swap notes" — support@zoodata.ai anytime, or right here in this thread. Feedback like this is worth more than the upvotes.
@kyle_dong The origin being knowable already, because extraction is deterministic, that's the part I didn't have. Most systems can't tell you where a value came from after the fact, so that's a real advantage.
One thing I'd add from acting on fields on the support side. Sourced-vs-inferred catches "did we read a labeled node". It doesn't catch "did we read the right one" when there is more than one.
Concrete: a customer has two open orders. We pull an order number and a tracking link, both clean strings, both straight from labeled fields, sourced = true on all of it. And it's the wrong order. Same on a product page, compare-at price and sale price are both clean numbers in labeled nodes. Read the strikethrough one and you are confidently wrong with sourced = true.
So for an agent that acts I think you want two bits, not one. Was it read from a labeled source, and was that source unambiguous, one plausible node, one entity it belongs to. The first you have. The second is where the confidently-wrong values actually sit for us.
Happy to swap notes on it, we've been chewing on the same thing…
the auto-escalate-to-full-model-extraction when core fields fail validation is a smart fallback. if a site is mid A/B rollout and flips between old/new layout per request, does that thrash the escalation path back and forth before the new template locks in, or is there a cooldown so you're not eating full-model cost on every call during the rollout window?
ZooData
@sabber_ahamed Good one. Per-request judgment is deliberate — during an A/B window old and new layouts interleave, so each request is handled on the page it actually got; a "lock-in switchover" would feed half the window to the wrong template. As for thrash cost: it points at us, not you — your price is flat per call, and the internal path never reaches your bill. How we protect ourselves (throttling, when things lock in) is an internal tuning problem. The contract is one line: thrash never reaches your results, and never reaches your bill.
One thing about dropping empty fields to save tokens: it makes the JSON shape shift from call to call. Our agent code ended up defaulting every field access because a missing `price` could mean the page had none or the extractor whiffed, and there's no way to tell which downstream. A stable schema with explicit nulls, or echoing back the resolved schema per page type, would fix that. Are you leaning stable-schema or minimal-payload long term?
ZooData
@dipankar_sarkar You've surfaced something we should carve into the docs, so let's state the contract plainly: absence ≡ not extracted. Whether the page truly had nothing or we failed to grab it — those two genuinely can't be distinguished today, so we don't pretend to: we won't hand you an explicit null that implies "we checked, the page really has none" (that's a guarantee we can't back). Absence means "no value obtained here." One meaning, full stop.
Under that contract, the "shape drift" is milder than it looks: the full field set per page_type is fixed — what varies is only which fields carried a value this time, and absence has exactly one meaning. Your defensive code collapses from "guess two meanings per field" into one global rule: not present = not obtained. Write it once, done.
On explicit-null stable schemas — we considered it, and landed here: since null and absence would carry the same information, sending nulls explicitly buys nothing but token cost. And the first-class consumer of this API is an agent: LLMs are natively robust to absence — "no price in the response" already is the complete information. It's strongly-typed glue code that needs every field present — and that's exactly the layer we hope keeps getting thinner in the agent era. So yes: long term, we're on team minimal payload.
That said, "should an agent-native API look like a traditional API" is a genuinely fun debate — if you disagree, keep this thread going, or take it long-form at support@zoodata.ai.
Totally fair not to fake a null you can't stand behind. My pain sat one level below the semantics: `price` showing up in one response and vanishing from the next meant every field access in our agent needed a guard, since parsing code leans on a stable shape. If each page type always emitted its full key set with the value simply absent, that alone fixes the shape, and the sourced-vs-not flag you floated with Jernej could carry the did-we-check honesty on top. Does the fixed-per-page-type schema you mentioned to hazy already give me that stable key set, or can fields still drop out per call?
ZooData
@dipankar_sarkar Honest answer: keys can still drop today — what's "fixed" is each page_type's possible field set (docs level), not the wire payload (sparse; absent means gone). But a fixed full set makes your fix a one-liner: hydrate missing keys to null against the known set at the boundary, and everything downstream sees a stable shape — N guards collapse into 1 hydration. Your layering — full keys fix shape, sourced flag carries honesty — is the right decomposition, exactly where the Jernej thread converged as the opt-in direction.
Boundary hydration against the known key set is exactly the fix, and the bonus is our static types stop lying: once every key is present the declared shape and the runtime object finally agree. One thing that bites later though, if you add a field to a page_type down the road my hydration set silently goes stale and I'm back to drift with no signal. So whatever field set you publish, stamp a version on it and I'll pin to that.
ZooData
@dipankar_sarkar "Our static types stop lying" — we're stealing that line 😄
The staleness problem you're pointing at is real, and worth spelling out both failure shapes: after we add a field, your pinned hydration set dies one of two ways — strict parsers shatter (unknown key rejected), lenient parsers silently leak (new data you never see). Neither gives you a signal, and the second is the more insidious.
So, plainly: no version stamp today. But what you're asking for is right, and it's the cheapest contract of its kind — a monotonic version per page_type field set; you pin it, a bump is your signal, and you decide when to follow. The request is already precise enough that there's nothing left for us to design — noted, and noted heavily.
Until it exists, one practical note: stay tolerant of unknown keys when hydrating (no strict-reject) — that way a future added field degrades to "new data you don't read yet" instead of a parse break. Combined with our "absence ≡ not extracted" contract, your shape layer holds today; what the version stamp adds is the signal for when to update it.
Great launch! The token math is the part that really matters, at least for agents. Paying to filter boilerplate out of 'clean' markdown is a tax you don't price in until the bill shows up! Wondering - when a site quietly ships a layout change or runs an A/B test, does that learned template keep mapping to the old fields and hand back a confidently wrong value?
ZooData
@artstavenka1 This is the question to ask any extraction system — "fast but wrong" is far scarier than "slow." Our defense: templates are never trusted unconditionally; every request is validated. Extraction output must pass core-field and type checks, and the moment a page stops matching expectations (missing/abnormal core fields), that request auto-escalates to full model extraction — the same slow path a brand-new page type takes. In other words, the default failure mode of a layout change is degrading to "slower but correct," not "fast but confidently wrong."
And an honest caveat: if an A/B variant happens to yield a value that's type-valid but semantically wrong, no extraction system can rule that out 100%. We run continuous quality evals against live pages to catch that kind of drift — and if you ever hit a confidently-wrong value in the wild, send it to support@zoodata.ai. We treat those as bugs, not noise.