Prompt template · Data
JSON extraction prompt for structured data
Pull fields from emails, documents or pages into a fixed JSON shape, with null instead of guesses. Free to copy, or open it in the prompt builder to fill the variables and get the exact API request.
194 tokens unfilled · 335 with the example below · o200k_base (GPT-4o and later)
Template
The prompt
Paste this into a chat window and replace each {{variable}}, or open it in the prompt builder to fill them in a form. Sections are marked with XML tags, which every major model reads well.
You extract structured data from text accurately. You never guess a value that the text doesn’t state.
<context>
<document>
{{document}}
</document>
</context>
<constraints>
- Use only information stated in the document. If a field isn’t there, use null. Don’t infer it from context or general knowledge.
- Copy names, IDs and amounts exactly as written. Normalise only where the shape says so: dates to YYYY-MM-DD, amounts to numbers without currency symbols.
- If a value is ambiguous (two different dates could be the due date), use null and explain in the "notes" field.
- Include every key in the shape, even when its value is null.
</constraints>
<output_format>
Only the JSON object. No code fences, no text before or after it.
</output_format>
<task>
Extract the fields below from the document and return them as JSON matching this shape:
{{json_shape}}
</task>For an API call: system prompt and user message
With a system prompt, the role, constraints and output format stay fixed across calls (and can be cached), while the context and task go in the user message.
You extract structured data from text accurately. You never guess a value that the text doesn’t state.
<constraints>
- Use only information stated in the document. If a field isn’t there, use null. Don’t infer it from context or general knowledge.
- Copy names, IDs and amounts exactly as written. Normalise only where the shape says so: dates to YYYY-MM-DD, amounts to numbers without currency symbols.
- If a value is ambiguous (two different dates could be the due date), use null and explain in the "notes" field.
- Include every key in the shape, even when its value is null.
</constraints>
<output_format>
Only the JSON object. No code fences, no text before or after it.
</output_format><context>
<document>
{{document}}
</document>
</context>
<task>
Extract the fields below from the document and return them as JSON matching this shape:
{{json_shape}}
</task>Variables
What to put in each variable
- {{document}}
- The source text: an email, an invoice, a PDF converted to text, a web page.
- {{json_shape}}
- The keys and types you want, as an example object or a JSON Schema. Include a "notes" string field for ambiguities.
Use
When to use it
Use it to turn unstructured text into records: invoices into accounting rows, support emails into ticket fields, CVs into a candidate table, product pages into catalogue entries. It suits any pipeline where a program, not a person, reads the output.
In production, pair it with your provider’s structured outputs feature so the JSON is guaranteed to parse and match the schema. The prompt still matters: the schema controls the shape, while the instructions control whether the values are true.
Structure
Why it’s structured this way
The strongest rule is “null instead of a guess”. Extraction models are tempted to fill every field, and a plausible invented due date is far worse than an empty one, because nothing downstream will catch it. Asking for every key, even when null, keeps the shape stable for the parser.
Copying values exactly, with normalisation only where specified, avoids subtle corruption: reformatted names, rounded amounts, invoice numbers with characters dropped. The notes field gives ambiguity somewhere to go instead of being silently resolved.
The output line asks for only the JSON, with no fences or commentary, so it can go straight into a parser when structured outputs aren’t available. If it still arrives wrapped in text, the JSON repair tool can extract and fix it, and the guide to invalid JSON from LLMs explains why it breaks.
Example
A filled-in example
- {{document}}
From: accounts@northwind-supplies.example Subject: Invoice NW-20931 Hi, please find invoice NW-20931 for October. Total due: £1,284.50 (incl. VAT). Payment terms 30 days from the invoice date of 3 October 2026. PO ref: 77-1042.
- {{json_shape}}
{ "supplier_email": "string", "invoice_number": "string", "total": "number", "currency": "ISO 4217 code", "invoice_date": "YYYY-MM-DD", "due_date": "YYYY-MM-DD or null", "po_number": "string or null", "notes": "string or null" }
What to look for. The due date isn’t written, only implied (30 days from 3 October). Under the rules it should be null with a note explaining the terms, rather than a computed 2 November that your accounting system might treat as stated fact.
The complete filled-in prompt (335 tokens)
You extract structured data from text accurately. You never guess a value that the text doesn’t state.
<context>
<document>
From: accounts@northwind-supplies.example
Subject: Invoice NW-20931
Hi, please find invoice NW-20931 for October. Total due: £1,284.50 (incl. VAT).
Payment terms 30 days from the invoice date of 3 October 2026. PO ref: 77-1042.
</document>
</context>
<constraints>
- Use only information stated in the document. If a field isn’t there, use null. Don’t infer it from context or general knowledge.
- Copy names, IDs and amounts exactly as written. Normalise only where the shape says so: dates to YYYY-MM-DD, amounts to numbers without currency symbols.
- If a value is ambiguous (two different dates could be the due date), use null and explain in the "notes" field.
- Include every key in the shape, even when its value is null.
</constraints>
<output_format>
Only the JSON object. No code fences, no text before or after it.
</output_format>
<task>
Extract the fields below from the document and return them as JSON matching this shape:
{
"supplier_email": "string",
"invoice_number": "string",
"total": "number",
"currency": "ISO 4217 code",
"invoice_date": "YYYY-MM-DD",
"due_date": "YYYY-MM-DD or null",
"po_number": "string or null",
"notes": "string or null"
}
</task>Models
Tips by model family
- OpenAI GPT
OpenAI’s Structured Outputs require every field in
required; make a field optional with a union such as["string", "null"], which fits the null-instead-of-guess rule exactly. - Claude
Anthropic’s structured outputs (
output_config.format) constrain Claude’s reply to your schema. Without it, the format line is what replaces the old prefill trick, which Claude 4.6 models and later reject with a 400 error. - Gemini
Gemini takes a schema with
response_formatfor structured output. Google warns that very large or deeply nested schemas may be rejected, so keep the shape flat where you can.
Related
Related templates and tools
- Classify textSort text into fixed labels with definitions, examples and an “unclear” option, returning JSON.
- Clean and normalise dataNormalise messy records to your rules, flag the rows it can’t fix, and never drop or invent data.
- SQL from a schemaTurn a question in plain English into one query for your schema and SQL dialect, with assumptions stated.
Building this into an app that sends the same instructions with every request? Start from a system prompt instead; each comes with design notes, failure modes and a monthly cost. In the system prompt library: JSON-only extraction service.
Edited the template? Compare your version with this one in the prompt diff, and count it for your model with the token counter. In the glossary: structured outputs, hallucination. Browse all 29 prompt templates.