HTML table to JSON/CSV
POST /api/html-tableExtract a <table> from an HTML string as JSON rows (header-keyed) or CSV. Send POST /api/html-table with the required field html and pay $0.001 per call over x402 or MPP, or call it free by solving a proof-of-work challenge. It returns a JSON object with rows, headers, format and count.
Useful for prices, schedules, sports stats, or anything an agent has already fetched as HTML. If multiple tables match, the first is used.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
html | string | yes | Raw HTML string containing the table (max 5MB) Also accepted as content, body, markup, text, source. |
selector | string | no | CSS selector for the table (default "table") |
format | string | no | "json" (default - rows as header-keyed objects) | "csv" |
Example request
curl -i -X POST https://agent402.tools/api/html-table \
-H "Content-Type: application/json" \
-d '{"html":"<table><thead><tr><th>City</th><th>Pop</th></tr></thead><tbody><tr><td>NYC</td><td>8.3M</td></tr><tr><td>LA</td><td>3.9M</td></tr></tbody></table>","format":"json"}'
Without payment this returns HTTP 402 Payment Required with the exact price for html-table; any x402 v2 or MPP client pays it and retries.
Example response
{
"rows": [
{
"City": "NYC",
"Pop": "8.3M"
},
{
"City": "LA",
"Pop": "3.9M"
}
],
"headers": [
"City",
"Pop"
],
"format": "json",
"count": 2
}
| Field | Type | Always present | In the example |
|---|---|---|---|
rows | array of objects | yes | 2 items in the example |
headers | array of string | yes | 2 items in the example |
format | string | yes | json |
count | number | yes | 2 |
From an MCP client
catalog.call {
"slug": "html-table",
"params": {
"html": "<table><thead><tr><th>City</th><th>Pop</th></tr></thead><tbody><tr><td>NYC</td><td>8.3M</td></tr><tr><td>LA</td><td>3.9M</td></tr></tbody></table>",
"format": "json"
}
}
On the hosted connector at https://agent402.tools/mcp, catalog.call runs html-table free (rate-limited, no wallet). Local install: npx -y agent402-mcp.
Errors and behavior
htmlis required. An input the tool rejects returns an HTTP 4xx whose body carrieserror,tool,expected,requiredandexample, so the caller can correct it.- A paid call that ends in any status of 400 or above is not charged over x402, MPP or a prepaid credits key: settlement is cancelled when the tool fails. The exception is a Tempo push credential, a transfer the buyer sent before the call: it settles before the tool runs, so if the tool then fails the payment is recorded as a refund owed to the paying wallet.
- Free tier: no outbound network call leaves the server for this tool, so proof-of-work (16 leading zero bits of sha256) pays for it.
- A
GETorHEADto /api/html-table returns the same 402 quote, so the price can be read without a body. - An
Idempotency-Keyheader makes a retried paid call replay the first 200 instead of charging again (an answer larger than 1 MB is not replayed).
Paid call (JavaScript agent)
import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client } from "@x402/core/client";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const client = new x402Client();
client.setSpendControls?.(false); // keep your own spending ceiling in code
registerExactEvmScheme(client, { signer: privateKeyToAccount(KEY) });
const payFetch = wrapFetchWithPayment(fetch, client);
const res = await payFetch("https://agent402.tools/api/html-table", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
"html": "<table><thead><tr><th>City</th><th>Pop</th></tr></thead><tbody><tr><td>NYC</td><td>8.3M</td></tr><tr><td>LA</td><td>3.9M</td></tr></tbody></table>",
"format": "json"
}),
});
No wallet? Pay with compute
Fetch a challenge, solve the sha256 puzzle (16 leading zero bits, a fraction of a second of CPU), and resend with the X-Pow-Solution header:
import { createHash } from "node:crypto";
const lz = (b) => { let t = 0; for (const x of b) { if (!x) { t += 8; continue; } t += Math.clz32(x) - 24; break; } return t; };
const c = await (await fetch("https://agent402.tools/api/pow/challenge?slug=html-table")).json();
let n = 0;
while (lz(createHash("sha256").update(c.challenge + ":" + n).digest()) < c.difficulty) n++;
await fetch("https://agent402.tools/api/html-table", { method: "POST", headers: { "X-Pow-Solution": c.token + ":" + n, "Content-Type": "application/json" }, body: JSON.stringify({"html":"<table><thead><tr><th>City</th><th>Pop</th></tr></thead><tbody><tr><td>NYC</td><td>8.3M</td></tr><tr><td>LA</td><td>3.9M</td></tr></tbody></table>","format":"json"}) });
Part of these workflows
HTML table to JSON/CSV is one step in this skill pack, each sold as a single call:
- Structured scrape - Pull structured data out of any web page deterministically - articles to clean text, tables to JSON rows, specific elements via CSS selector - without writing regex against raw HTML.
Related tools
HTML select
POST /api/html-selectRun a CSS selector against an HTML string and return the matches (text, attrs, and optionally outerHTML for each). The d…
HTML links
POST /api/html-linksEnumerate every <a href> in an HTML string with its anchor text and rel attribute. Optionally resolves relative hrefs ag…
Exa page contents
POST /api/exa-contentsRetrieve the readable text of up to 10 web pages by URL, with optional query-focused highlights. Exa serves from its cra…
HTML meta (from string)
POST /api/html-metaExtract <title>, <meta description>, OpenGraph/Twitter cards, canonical URL, and JSON-LD blocks from an HTML string. Dis…
HTML strip to text
POST /api/html-stripStrip all HTML tags and return plain text. Preserves block-level structure (paragraphs and headings become newline-separ…
Extract / split PDF pages
POST /api/pdf-extract-pagesPull a subset of pages into a new PDF (split). Body: {"url":"https://…/file.pdf","pages":"1-3,5"}. Returns the new PDF a…