JSON Schema generator for the data you want off a page
Paste the JSON you wish you had and get the schema that describes it, with types, required fields and room for the descriptions a model actually reads. The extract request that uses it is shown beside it.
Paste a sample object such as one order line, or start from an empty schema and add fields by name. Everything runs in your browser.
This tool runs in your browser and needs JavaScript.
Observations, not verdicts. What you enter is processed for this result and written to a usage journal described in the privacy policy; nothing else is stored.
Where the schema goes
An extraction takes the schema as its only required argument and returns data shaped by it.
curl -X POST https://browserberg.com/v1/sessions/$SESSION_ID/extract \
-H "Authorization: Bearer $BROWSERBERG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"schema": {
"type": "object",
"properties": {
"invoiceNumber": { "type": "string", "description": "The number printed in the header" },
"total": { "type": "number", "description": "Gross amount in EUR" },
"dueDate": { "type": "string", "description": "ISO 8601 date" }
},
"required": ["invoiceNumber", "total"]
}
}'
import { Browserberg } from '@browserberg/sdk';
const bb = new Browserberg({ apiKey: process.env.BROWSERBERG_API_KEY });
await using session = await bb.sessions.create();
await session.act({ steps: [{ action: 'navigate', value: 'https://portal.example/invoices/4711' }] });
const { data } = await session.extract({
schema: {
type: 'object',
properties: {
invoiceNumber: { type: 'string', description: 'The number printed in the header' },
total: { type: 'number', description: 'Gross amount in EUR' },
},
required: ['invoiceNumber', 'total'],
},
});
console.log(data);
from browserberg import Browserberg
bb = Browserberg(api_key=API_KEY)
with bb.sessions.create() as s:
s.act(steps=[{"action": "navigate", "value": "https://portal.example/invoices/4711"}])
result = s.extract(schema={
"type": "object",
"properties": {
"invoiceNumber": {"type": "string"},
"total": {"type": "number", "description": "Gross amount in EUR"},
},
"required": ["invoiceNumber", "total"],
})
print(result["data"])
From a sample to a schema
-
Paste one representative object
A single record with every field you care about. Arrays are fine; the generator merges the types it sees across the elements.
-
Check the inferred types
Integers become integer, decimals number, null becomes a nullable type. Anything the sample got wrong is editable in place.
-
Add descriptions
A description on a property is the instruction the model reads for that field. Say where the value is on the page and in what unit; a bare type is a guess.
-
Copy the request
The extract call on the right updates as you edit. Validation problems in the schema are listed above it and block the copy button until fixed.
How inference works and what a schema can and cannot do
The generator walks the JSON you paste and produces a schema that would accept it. An object becomes type: object with one property per key, an array becomes items with the union of the element types, a whole number becomes integer and a fraction number, null widens the property to a nullable type. Every key present in the sample is put in required by default, which you should prune: an optional field the page lacks is dropped cleanly, while a required one is kept and flagged as suspect, and a flag is easier to miss than an absence.
What the schema does inside an extraction
An extract call takes the schema and the page the session is currently on. The page is rendered by the same perception layer the agent uses, fenced as untrusted content, and handed with the schema to a model hosted in the EU. The answer is then grounded before it is returned as data: every string value the model produced must appear in the text it was shown, and one that does not is dropped with a warning. Numbers and booleans are not checked, because a count or a yes/no is derived rather than quoted. The schema therefore does three jobs at once: it tells the model what to look for, it constrains the shape of the answer, and it is the contract your code parses. A description on a property is the part the model reads most carefully. "Gross amount in EUR including VAT" gets a different answer from "total", and the tool leaves room for it on every property.
What the generator validates
The schema itself is checked: unknown keywords, a required entry with no matching property, an items on something that is not an array, a type name that does not exist. These are the mistakes that surface as a 400 from the API, and they are listed above the request preview as you type.
What it does not judge
A schema cannot make a value exist. If the page has no due date, no description will conjure one, and a required field the page lacks comes back flagged in warnings as required by the schema but absent from the page, rather than as a value to trust. Model the uncertainty in the schema: make the field nullable, or describe the fallback. The generator also validates no data against the schema, only the schema against the specification, so a sample that is itself wrong produces a schema that is faithfully wrong. And it knows nothing about the page. Whether the field you named is visible without scrolling, sits behind a tab or lives in a PDF the page links to are questions for the agent view and for the extraction itself.
Keep schemas small. A page rarely holds forty facts you need, and every property is one more thing the model can get subtly wrong. Ten well-described fields beat forty bare ones.
Questions about JSON Schema for extraction
How do I generate a JSON Schema from a JSON example?
Paste the example into this tool. Objects, arrays, numbers, strings, booleans and nulls are mapped to their schema types, all keys are marked required, and the result is editable before you copy it.
Which JSON Schema keywords does the extract call understand?
The structural core: type, properties, required, items, enum, description and nullable types. Exotic keywords are flagged by this tool's validator rather than silently passed on.
Do descriptions really change the result?
Yes. The description is what the model reads to find the value on the page. A unit, a location on the page or an example format in the description is the cheapest accuracy improvement available.
What happens when a required field is not on the page?
The field is kept but listed in warnings as required by the schema yet absent from the page, so your code can decide. An optional field that is not on the page is dropped with a warning instead. Make a field optional when a page may legitimately lack it.
Is my sample JSON uploaded?
No. The generator runs in your browser. Only the extract call you copy from it, when you run it yourself, sends the schema to the API.
Run the schema against a real page
Five browser hours, no card. Open a session, navigate, extract, and get data shaped exactly as you described.