Docs
Dashboard
Examples / Data outBeta

Prices by country

Open the same product page through residential proxies in three countries and compare the prices side by side, with the country each request really came from.

When to use it: You need to see a page the way visitors in other countries see it, such as their prices.

Usesfetch and extract with a proxy per request
Needsa plan with residential proxies (the traffic counts against its allowance) and a model on the API
Sitea books.toscrape.com product page, and Cloudflare's trace page for the exit country
Outputoutput/result.json: one row per country
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.

/** * Prices by country: the same product page through residential proxies in three countries, side by side, with the * country each request really came from. * *   npx tsx node/index.ts            (BOXLINE_API_KEY; PRODUCT_URL, COUNTRIES=US,DE,GB; a plan with residential proxies) * * Proxy traffic counts against the plan's allowance. Writes output/result.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 countries = (process.env.COUNTRIES ?? "US,DE,GB").split(",").map((c) => c.trim().toUpperCase()).filter(Boolean);const bx = new Boxline();const rows = [];let modelUsd = 0;for (const country of countries) {  const proxy = { type: "residential" as const, country };  // Where the site sees the request from: Cloudflare's trace page names the country of the address it came from.  const trace = await bx.fetch("https://www.cloudflare.com/cdn-cgi/trace", { format: "text", proxy });  const seenFrom = /^loc=([A-Z]{2})$/m.exec(trace.content)?.[1] ?? null;  // The product's price as that visitor sees it.  const { data, usage } = await bx.extract<{ price: number; currency: string; shown: string }>({    url,    proxy,    prompt: "The product's price as shown on the page.",    schema: {      type: "object",      properties: { price: { type: "number" }, currency: { type: "string", description: "ISO 4217 code" }, shown: { type: "string", description: "the price exactly as the page shows it" } },      required: ["price", "currency", "shown"],    },  });  modelUsd += usage.costUsd;  rows.push({ country, seenFrom, ...data });  console.log(`${country}: seen from ${seenFrom}, ${data.shown} (${data.price} ${data.currency})`);}console.table(rows);mkdirSync(out, { recursive: true });writeFileSync(join(out, "result.json"), JSON.stringify({ url, rows, usage: { modelUsd } }, null, 2));

Inputs

Environment variables the example reads:

  • PRODUCT_URL: the product page (default https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html).
  • COUNTRIES: the proxies' countries (default US,DE,GB).

Run it

Get the examples with git clone https://github.com/Boxline-dev/examples.git and open this one: cd examples/prices-by-country. 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.

Every request came from its country and every row has a price.

Source

github.com/Boxline-dev/examples/prices-by-country 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.