Docs
Dashboard
Examples / FormsBeta

Company details from its legal pages

Crawl a site's pages, pick its terms, privacy and imprint pages, and have a model read the organisation's legal name and postal address from them.

When to use it: You need an organisation's legal name and postal address from its own website.

Usescrawl (depth 1), extract with several urls and a schema
Needsa model on the API
Siteany site; the default is eff.org. The runner uses its stand-in company site (terms, privacy notice and a blog)
Outputoutput/company.json
LanguagesNode and Python

The code

The example as it is in its folder. Both versions do the same job and write the same output/, so one result check covers both.

/** * Company details from its legal pages: crawl a site's pages, pick its terms, privacy and imprint pages, and have a * model read the organisation's legal name and postal address from them. * *   npx tsx node/index.ts            (BOXLINE_API_KEY; SITE_URL for another site) * * Writes output/company.json. */import { mkdirSync, writeFileSync } from "node:fs";import { join } from "node:path";import { Boxline } from "@boxline/sdk";const out = process.env.OUTPUT_DIR ?? "output";const site = process.env.SITE_URL ?? "https://www.eff.org/";const bx = new Boxline();// 1. The start page and the pages it links to (same site, robots.txt respected).const job = await bx.crawl.start({ url: site, maxPages: 40, maxDepth: 1, format: "text" });const crawl = await bx.crawl.wait(job.id, { pollMs: 1500, timeoutMs: 10 * 60_000 });const LEGAL = /terms|privacy|legal|imprint|impressum|about|contact|policy/i;const legal = crawl.data  .filter((p) => !p.error && (p.status ?? 0) < 400 && (LEGAL.test(new URL(p.url).pathname) || LEGAL.test(p.title ?? "")))  .sort((a, b) => Number(/privacy|imprint|impressum|legal/i.test(b.url)) - Number(/privacy|imprint|impressum|legal/i.test(a.url)))  .slice(0, 4);console.log(`${crawl.data.length} pages crawled; reading ${legal.length}: ${legal.map((p) => new URL(p.url).pathname).join(", ")}`);if (!legal.length) throw new Error("no terms, privacy or imprint page is linked from the start page");// 2. A model reads them into a fixed shape (the pages render in a real browser; their text is treated as data).const { data, usage } = await bx.extract<{ legalName: string; address: string; foundOn: string }>({  urls: legal.map((p) => p.finalUrl ?? p.url),  prompt: "The legal name and postal address of the organisation that runs this website, and the address (URL) of the page that says so.",  schema: {    type: "object",    properties: { legalName: { type: "string" }, address: { type: "string", description: "the postal address on one line" }, foundOn: { type: "string" } },    required: ["legalName", "address", "foundOn"],  },});console.log(`${data.legalName}, ${data.address} (from ${data.foundOn})`);mkdirSync(out, { recursive: true });writeFileSync(join(out, "company.json"), JSON.stringify(data, null, 2));writeFileSync(join(out, "result.json"), JSON.stringify({ site, read: legal.map((p) => p.finalUrl ?? p.url), company: data, usage: { modelUsd: usage.costUsd } }, null, 2));

Inputs

Environment variables the example reads:

  • SITE_URL: the site (default https://www.eff.org/).

Run it

Get the examples with git clone https://github.com/Boxline-dev/examples.git and open this one: cd examples/company-details-from-legal-pages. Put your API key in BOXLINE_API_KEY (and BOXLINE_API_URL for another API), then run either version from the example’s folder. Both write to output/ and stop their sessions when they finish.

# Node 18 or newer, in the example's folderexport BOXLINE_API_KEY=…   # your API keynpm install @boxline/sdk tsxnpx tsx node/index.ts

Then check the result, from the same folder: npx tsx check.ts output. It exits with 0 only when the result is right.

What its check proves

check.ts reads what the example wrote and passes only when the result is right, not merely when the example ran.

On the stand-in, the legal name and address come from the privacy notice, and the blog was not read.

Source

github.com/Boxline-dev/examples/company-details-from-legal-pages on GitHub, with its README.md, check.ts and .env.example. The examples are open source. See all examples.

These docs describe a beta API. Endpoints, fields and SDK methods may change before general availability; breaking changes will be listed in the changelog.