Skip to main content
Perplexity

Search documentation

Type to search this documentation.

On this pageOverview

Structured Output Extraction

This guide shows how to extract structured, typed JSON from the Agent API using the response_format parameter with JSON schemas. You will learn practical patterns for product data extraction, research findings, comparison tables, and building reliable data pipelines — all with guaranteed schema conformance.

Install the Perplexity SDK:

Python
pip install perplexityai
TypeScript
npm install @perplexity-ai/perplexity_ai

If you don't have an API key yet:

Get your Perplexity API Key

Navigate to the API Keys tab in the API Portal and generate a new key.

Click here

Then export your API key as an environment variable:

Bash
export PERPLEXITY_API_KEY="your-api-key"

When you pass response_format with type: "json_schema", the Agent API constrains the model's output to match your schema exactly. The response in output_text is a valid JSON string you can parse directly.

The schema format follows JSON Schema with a few constraints specific to the Perplexity API:

  • No recursive schemas. The schema cannot reference itself.
  • No unconstrained objects. Avoid additionalProperties: true or bare object types without defined properties.
  • Named schemas required. Each schema needs a name field for identification.

Extract structured data about a single topic with web search grounding.

Python
import json
from perplexity import Perplexity

client = Perplexity()

response = client.responses.create(
    model="openai/gpt-5.6-terra",
    input="What is the current market cap, CEO, and founding year of NVIDIA?",
    tools=[{"type": "web_search"}],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "company_profile",
            "schema": {
                "type": "object",
                "properties": {
                    "company_name": {"type": "string"},
                    "ticker": {"type": "string"},
                    "ceo": {"type": "string"},
                    "founded_year": {"type": "integer"},
                    "market_cap_usd": {"type": "string"},
                    "sector": {"type": "string"},
                    "headquarters": {"type": "string"},
                },
                "required": ["company_name", "ticker", "ceo", "founded_year", "market_cap_usd", "sector", "headquarters"],
                "additionalProperties": false,
            },
        },
    },
)

company = json.loads(response.output_text)
print(f"{company['company_name']} ({company['ticker']})")
print(f"  CEO: {company['ceo']}")
print(f"  Founded: {company['founded_year']}")
print(f"  Market Cap: {company['market_cap_usd']}")
print(f"  Sector: {company['sector']}")
TypeScript
import Perplexity from '@perplexity-ai/perplexity_ai';

const client = new Perplexity();

const response = await client.responses.create({
    model: "openai/gpt-5.6-terra",
    input: "What is the current market cap, CEO, and founding year of NVIDIA?",
    tools: [{ type: "web_search" }],
    response_format: {
        type: "json_schema",
        json_schema: {
            name: "company_profile",
            schema: {
                type: "object",
                properties: {
                    company_name: { type: "string" },
                    ticker: { type: "string" },
                    ceo: { type: "string" },
                    founded_year: { type: "integer" },
                    market_cap_usd: { type: "string" },
                    sector: { type: "string" },
                    headquarters: { type: "string" },
                },
                required: ["company_name", "ticker", "ceo", "founded_year", "market_cap_usd", "sector", "headquarters"],
            },
        },
    },
});

const company = JSON.parse(response.output_text);
console.log(`${company.company_name} (${company.ticker})`);
console.log(`  CEO: ${company.ceo}`);
console.log(`  Founded: ${company.founded_year}`);
console.log(`  Market Cap: ${company.market_cap_usd}`);
console.log(`  Sector: ${company.sector}`);

Extract a structured comparison of multiple items from a single query.

Python
import json
from perplexity import Perplexity

client = Perplexity()

response = client.responses.create(
    model="openai/gpt-5.6-terra",
    input="Compare the top 3 electric vehicles under $40,000 available in the US in 2026",
    tools=[{"type": "web_search"}],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "ev_comparison",
            "schema": {
                "type": "object",
                "properties": {
                    "vehicles": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "make": {"type": "string"},
                                "model": {"type": "string"},
                                "year": {"type": "integer"},
                                "starting_price_usd": {"type": "integer"},
                                "range_miles": {"type": "integer"},
                                "battery_kwh": {"type": "number"},
                                "pros": {"type": "array", "items": {"type": "string"}},
                                "cons": {"type": "array", "items": {"type": "string"}},
                            },
                            "required": ["make", "model", "year", "starting_price_usd", "range_miles", "battery_kwh", "pros", "cons"],
                            "additionalProperties": false,
                        },
                    },
                    "comparison_date": {"type": "string"},
                },
                "required": ["vehicles", "comparison_date"],
                "additionalProperties": false,
            },
        },
    },
)

data = json.loads(response.output_text)
print(f"EV Comparison (as of {data['comparison_date']})\n")

for v in data["vehicles"]:
    print(f"{v['year']} {v['make']} {v['model']}")
    print(f"  Price: ${v['starting_price_usd']:,}")
    print(f"  Range: {v['range_miles']} mi | Battery: {v['battery_kwh']} kWh")
    print(f"  Pros: {', '.join(v['pros'])}")
    print(f"  Cons: {', '.join(v['cons'])}")
    print()
TypeScript
import Perplexity from '@perplexity-ai/perplexity_ai';

const client = new Perplexity();

const response = await client.responses.create({
    model: "openai/gpt-5.6-terra",
    input: "Compare the top 3 electric vehicles under $40,000 available in the US in 2026",
    tools: [{ type: "web_search" }],
    response_format: {
        type: "json_schema",
        json_schema: {
            name: "ev_comparison",
            schema: {
                type: "object",
                properties: {
                    vehicles: {
                        type: "array",
                        items: {
                            type: "object",
                            properties: {
                                make: { type: "string" },
                                model: { type: "string" },
                                year: { type: "integer" },
                                starting_price_usd: { type: "integer" },
                                range_miles: { type: "integer" },
                                battery_kwh: { type: "number" },
                                pros: { type: "array", items: { type: "string" } },
                                cons: { type: "array", items: { type: "string" } },
                            },
                            required: ["make", "model", "year", "starting_price_usd", "range_miles", "battery_kwh", "pros", "cons"],
                        },
                    },
                    comparison_date: { type: "string" },
                },
                required: ["vehicles", "comparison_date"],
            },
        },
    },
});

const data = JSON.parse(response.output_text);
console.log(`EV Comparison (as of ${data.comparison_date})\n`);

for (const v of data.vehicles) {
    console.log(`${v.year} ${v.make} ${v.model}`);
    console.log(`  Price: $${v.starting_price_usd.toLocaleString()}`);
    console.log(`  Range: ${v.range_miles} mi | Battery: ${v.battery_kwh} kWh`);
    console.log(`  Pros: ${v.pros.join(", ")}`);
    console.log(`  Cons: ${v.cons.join(", ")}`);
    console.log();
}

Parse search-grounded research into a structured format suitable for reports or databases.

Python
import json
from perplexity import Perplexity

client = Perplexity()

response = client.responses.create(
    model="openai/gpt-5.6-terra",
    input="What are the most recent clinical trial results for GLP-1 receptor agonists in treating obesity?",
    tools=[{"type": "web_search"}],
    instructions="Provide findings from the most recent clinical trials. Include specific numbers and trial names where available.",
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "research_findings",
            "schema": {
                "type": "object",
                "properties": {
                    "topic": {"type": "string"},
                    "findings": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "trial_name": {"type": "string"},
                                "drug": {"type": "string"},
                                "phase": {"type": "string"},
                                "key_result": {"type": "string"},
                                "sample_size": {"type": "string"},
                                "publication_year": {"type": "integer"},
                            },
                            "required": ["trial_name", "drug", "phase", "key_result", "sample_size", "publication_year"],
                            "additionalProperties": false,
                        },
                    },
                    "summary": {"type": "string"},
                },
                "required": ["topic", "findings", "summary"],
                "additionalProperties": false,
            },
        },
    },
)

data = json.loads(response.output_text)
print(f"Topic: {data['topic']}\n")
print(f"Summary: {data['summary']}\n")

for finding in data["findings"]:
    print(f"  {finding['trial_name']} ({finding['drug']}, Phase {finding['phase']})")
    print(f"    Result: {finding['key_result']}")
    print(f"    N={finding['sample_size']}, Published: {finding['publication_year']}")
    print()
TypeScript
import Perplexity from '@perplexity-ai/perplexity_ai';

const client = new Perplexity();

const response = await client.responses.create({
    model: "openai/gpt-5.6-terra",
    input: "What are the most recent clinical trial results for GLP-1 receptor agonists in treating obesity?",
    tools: [{ type: "web_search" }],
    instructions: "Provide findings from the most recent clinical trials. Include specific numbers and trial names where available.",
    response_format: {
        type: "json_schema",
        json_schema: {
            name: "research_findings",
            schema: {
                type: "object",
                properties: {
                    topic: { type: "string" },
                    findings: {
                        type: "array",
                        items: {
                            type: "object",
                            properties: {
                                trial_name: { type: "string" },
                                drug: { type: "string" },
                                phase: { type: "string" },
                                key_result: { type: "string" },
                                sample_size: { type: "string" },
                                publication_year: { type: "integer" },
                            },
                            required: ["trial_name", "drug", "phase", "key_result", "sample_size", "publication_year"],
                        },
                    },
                    summary: { type: "string" },
                },
                required: ["topic", "findings", "summary"],
            },
        },
    },
});

const data = JSON.parse(response.output_text);
console.log(`Topic: ${data.topic}\n`);
console.log(`Summary: ${data.summary}\n`);

for (const finding of data.findings) {
    console.log(`  ${finding.trial_name} (${finding.drug}, Phase ${finding.phase})`);
    console.log(`    Result: ${finding.key_result}`);
    console.log(`    N=${finding.sample_size}, Published: ${finding.publication_year}`);
    console.log();
}

Chain structured output extraction into a pipeline that queries, extracts, and stores structured data.

Python
import json
import csv
import io
from perplexity import Perplexity

client = Perplexity()

SCHEMA = {
    "type": "json_schema",
    "json_schema": {
        "name": "startup_funding",
        "schema": {
            "type": "object",
            "properties": {
                "companies": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "name": {"type": "string"},
                            "round": {"type": "string"},
                            "amount_usd": {"type": "string"},
                            "lead_investor": {"type": "string"},
                            "sector": {"type": "string"},
                            "date": {"type": "string"},
                        },
                        "required": ["name", "round", "amount_usd", "lead_investor", "sector", "date"],
                        "additionalProperties": false,
                    },
                },
            },
            "required": ["companies"],
            "additionalProperties": false,
        },
    },
}


def extract_funding_rounds(sector: str) -> list[dict]:
    """Query the API and return structured funding data for a sector."""
    response = client.responses.create(
        model="openai/gpt-5.6-terra",
        input=f"List the 5 largest startup funding rounds in {sector} from the past 3 months",
        tools=[{"type": "web_search"}],
        response_format=SCHEMA,
    )
    data = json.loads(response.output_text)
    return data["companies"]


def pipeline(sectors: list[str]) -> str:
    """Run extraction across multiple sectors and produce a CSV."""
    all_rows = []
    for sector in sectors:
        print(f"Extracting: {sector}...")
        rows = extract_funding_rounds(sector)
        for row in rows:
            row["query_sector"] = sector
            all_rows.append(row)

    # Convert to CSV
    output = io.StringIO()
    writer = csv.DictWriter(output, fieldnames=["query_sector", "name", "round", "amount_usd", "lead_investor", "sector", "date"])
    writer.writeheader()
    writer.writerows(all_rows)
    return output.getvalue()


if __name__ == "__main__":
    csv_output = pipeline(["AI infrastructure", "climate tech", "biotech"])
    print(csv_output)
JSON
// ✅ Flat object with typed fields
{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "count": { "type": "integer" },
    "tags": { "type": "array", "items": { "type": "string" } }
  },
  "required": ["name", "count", "tags"]
}

// ✅ Array of typed objects
{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "key": { "type": "string" },
      "value": { "type": "number" }
    },
    "required": ["key", "value"]
  }
}

// ✅ Enum for constrained values
{
  "type": "string",
  "enum": ["low", "medium", "high"]
}
JSON
// ❌ Recursive schema (self-referencing)
{
  "type": "object",
  "properties": {
    "children": { "$ref": "#" }
  }
}

// ❌ Unconstrained object
{
  "type": "object",
  "additionalProperties": true
}

// ❌ Bare dict/map type
{
  "type": "object"
}

Combining Structured Output with Function Calling

Section titled “Combining Structured Output with Function Calling”

You can use response_format alongside custom tools. The model calls your functions first, then formats the final response according to your schema.

Python
import json
from perplexity import Perplexity

client = Perplexity()

tools = [
    {"type": "web_search"},
    {
        "type": "function",
        "name": "get_internal_price",
        "description": "Look up the internal wholesale price for a product SKU.",
        "parameters": {
            "type": "object",
            "properties": {
                "sku": {"type": "string", "description": "Product SKU"}
            },
            "required": ["sku"]
        },
    },
]


def get_internal_price(sku: str) -> dict:
    prices = {"SKU-A100": 8500, "SKU-H100": 25000, "SKU-4090": 1600}
    return {"sku": sku, "wholesale_price_usd": prices.get(sku, 0)}


response = client.responses.create(
    model="openai/gpt-5.6-terra",
    tools=tools,
    input="Get the current retail price for the NVIDIA H100 GPU from the web, and also look up our internal wholesale price for SKU-H100. Compare them.",
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "price_comparison",
            "schema": {
                "type": "object",
                "properties": {
                    "product": {"type": "string"},
                    "retail_price_usd": {"type": "string"},
                    "wholesale_price_usd": {"type": "integer"},
                    "margin_percent": {"type": "string"},
                    "source": {"type": "string"},
                },
                "required": ["product", "retail_price_usd", "wholesale_price_usd", "margin_percent", "source"],
                "additionalProperties": false,
            },
        },
    },
)

# Handle function calls
while any(item.type == "function_call" for item in response.output):
    next_input = [item.model_dump() for item in response.output]
    for item in response.output:
        if item.type == "function_call":
            args = json.loads(item.arguments)
            result = get_internal_price(**args)
            next_input.append({
                "type": "function_call_output",
                "call_id": item.call_id,
                "output": json.dumps(result),
            })
    response = client.responses.create(
        model="openai/gpt-5.6-terra",
        tools=tools,
        input=next_input,
        response_format={
            "type": "json_schema",
            "json_schema": {
                "name": "price_comparison",
                "schema": {
                    "type": "object",
                    "properties": {
                        "product": {"type": "string"},
                        "retail_price_usd": {"type": "string"},
                        "wholesale_price_usd": {"type": "integer"},
                        "margin_percent": {"type": "string"},
                        "source": {"type": "string"},
                    },
                    "required": ["product", "retail_price_usd", "wholesale_price_usd", "margin_percent", "source"],
                    "additionalProperties": false,
                },
            },
        },
    )

data = json.loads(response.output_text)
print(f"Product: {data['product']}")
print(f"Retail: {data['retail_price_usd']} (from {data['source']})")
print(f"Wholesale: ${data['wholesale_price_usd']:,}")
print(f"Margin: {data['margin_percent']}")
Suggest an edit

Propose a replacement for this page. The site team reviews it before applying any changes.

Export
Documentation menu