Product page to JSON
Pull a product's name, price, stock and specs from its page into a fixed shape given as a JSON Schema.
When to use it: You want product data (price, stock, specs) in a fixed shape your code can rely on.
| Uses | extract with a schema |
|---|---|
| Needs | a model on the API (extract uses a fast, low-cost model by default) |
| Site | a books.toscrape.com product page (a demo shop) |
| Output | output/product.json |
| Languages | Node 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.
/** * Product page to JSON: pull name, price, stock and specs from a product page into a fixed shape (a JSON Schema). * * npx tsx node/index.ts (BOXLINE_API_KEY; PRODUCT_URL for your own product page) * * Writes output/product.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 url = process.env.PRODUCT_URL ?? "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html";const bx = new Boxline();interface Product { name: string; price: number; currency: string; inStock: boolean; stockCount: number | null; specs: { name: string; value: string }[];}// The page renders in a real browser inside a sandbox; a model fills the schema (page text is treated as data).const { data, pages, model, usage } = await bx.extract<Product>({ url, prompt: "The product on this page. specs: the rows of its product information table.", schema: { type: "object", properties: { name: { type: "string" }, price: { type: "number", description: "the price as a number, without the currency" }, currency: { type: "string", description: "ISO 4217 code, e.g. GBP" }, inStock: { type: "boolean" }, stockCount: { type: ["integer", "null"], description: "how many are available, when the page says" }, specs: { type: "array", items: { type: "object", properties: { name: { type: "string" }, value: { type: "string" } }, required: ["name", "value"] } }, }, required: ["name", "price", "currency", "inStock", "stockCount", "specs"], },});console.log(`${data.name}: ${data.price} ${data.currency}, ${data.inStock ? `in stock (${data.stockCount ?? "?"})` : "out of stock"}, ${data.specs.length} specs`);console.log(`Read ${pages[0]!.finalUrl} (HTTP ${pages[0]!.status}) with ${model} for $${usage.costUsd.toFixed(4)}`);mkdirSync(out, { recursive: true });writeFileSync(join(out, "product.json"), JSON.stringify(data, null, 2));writeFileSync(join(out, "result.json"), JSON.stringify({ url, product: data, model, usage: { modelUsd: usage.costUsd } }, null, 2));"""Product page to JSON: pull name, price, stock and specs from a product page into a fixed shape (a JSON Schema). python python/main.py (BOXLINE_API_KEY; PRODUCT_URL for your own product page)Writes output/product.json."""import jsonimport osfrom pathlib import Pathfrom boxline import Boxlineout = Path(os.environ.get("OUTPUT_DIR", "output"))url = os.environ.get("PRODUCT_URL", "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html")bx = Boxline()# The page renders in a real browser inside a sandbox; a model fills the schema (page text is treated as data).r = bx.extract( url=url, prompt="The product on this page. specs: the rows of its product information table.", schema={ "type": "object", "properties": { "name": {"type": "string"}, "price": {"type": "number", "description": "the price as a number, without the currency"}, "currency": {"type": "string", "description": "ISO 4217 code, e.g. GBP"}, "inStock": {"type": "boolean"}, "stockCount": {"type": ["integer", "null"], "description": "how many are available, when the page says"}, "specs": { "type": "array", "items": {"type": "object", "properties": {"name": {"type": "string"}, "value": {"type": "string"}}, "required": ["name", "value"]}, }, }, "required": ["name", "price", "currency", "inStock", "stockCount", "specs"], },)product = r["data"]stock = f"in stock ({product.get('stockCount')})" if product["inStock"] else "out of stock"print(f"{product['name']}: {product['price']} {product['currency']}, {stock}, {len(product['specs'])} specs")print(f"Read {r['pages'][0]['finalUrl']} (HTTP {r['pages'][0]['status']}) with {r['model']} for ${r['usage']['costUsd']:.4f}")out.mkdir(parents=True, exist_ok=True)(out / "product.json").write_text(json.dumps(product, indent=2, ensure_ascii=False))(out / "result.json").write_text(json.dumps({"url": url, "product": product, "model": r["model"], "usage": {"modelUsd": r["usage"]["costUsd"]}}, indent=2, ensure_ascii=False))Inputs
Environment variables the example reads:
PRODUCT_URL: your product page (defaulthttps://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html).
Run it
Get the examples with git clone https://github.com/Boxline-dev/examples.git and open this one: cd examples/product-to-json. 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# Python 3.9 or newer, in the example's folderexport BOXLINE_API_KEY=… # your API keypip install boxline-sdkpython python/main.pyThen 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.
Product.json matches the schema; for the default page: "A Light in the Attic", 51.77 GBP, in stock (22), UPC a897fe39b1053632.
Source
github.com/Boxline-dev/examples/product-to-json 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.