Back to blog
ChatGPT17 min read

How to Control Output Format (Tables, Lists, Markdown, JSON)

How to ask AI for the exact output shape you need: table, list, JSON, CSV, template, code block, or plain text, and the wording that keeps each one from drifting back into prose.

NH
Nafiul Hasan
Founder, Prompt Architects

TL;DR: Naming a format increases compliance, but it never guarantees it. For each format, name the exact shape, give a worked example, state a literal value for unknowns, forbid preamble and commentary, and put the instruction close to where the model generates the answer. Where a vendor offers real schema enforcement, that's a different, stronger mechanism than asking nicely.

Why Format Compliance Is a Tendency, Not a Guarantee

To control AI output format, you're not flipping a switch, you're weighting a request. Ask an AI model for a markdown table, a JSON object, or a numbered list, and it will usually give you one. "Usually" is the honest word. A prose instruction is a request the model weighs against every other signal in your prompt: the length of the conversation, an example earlier in the thread that showed a different shape, a competing instruction it decided mattered more. It complies most of the time and drifts back toward plain prose some of the time, and there's no way to predict which run you'll get from the wording alone.

That's not a reason to skip formatting instructions. It's a reason to write them the way this guide does: precisely enough that drift becomes rare, with a fallback plan for the runs where it still happens. Where a vendor's API offers actual schema enforcement rather than a polite request, that's worth knowing about too, and the difference between the two mechanisms matters more than which format you picked.

If you're still deciding which format actually fits the job in front of you, that's a separate question this page doesn't re-answer: How to Decide What Output Format You Actually Need covers the job-to-format mapping (comparisons need tables, sequences need steps, decisions need a verdict first) in depth. This page picks up from there. It assumes you already know roughly which of the eight shapes below you want, and gives you the exact wording that gets each one to stick, including the two shapes almost nothing else covers: asking for a fixed template, and asking for nothing formatted at all.

Five Things That Make Any Format Request Stick

These apply to all eight formats below. Skipping any one of them is the most common reason a format request that "should" work doesn't.

1. Show the shape, don't describe it. "Organize this as a table" leaves every decision open: how many columns, what order, whether there's commentary around it. A worked example of one row, with the instruction "match this shape, only change the values," removes the decision entirely. Models are far more consistent copying a concrete pattern than inferring one from an adjective.

2. Name the exact keys or column headers, in order. Not "give me the relevant fields." List them: Name, Price, Free tier. Order matters because the model will otherwise pick its own, and a downstream script or a person scanning the table both need the columns in a predictable place.

3. Choose the literal value for "I don't know," yourself. A model asked to fill in a table, a JSON field, or a CSV column will guess a plausible-looking value rather than leave a gap, because an empty cell reads to it as an unanswered question. State the exact placeholder you want: N/A, NOT STATED, null, 0. Which one you pick matters less than picking one and saying so explicitly.

4. Say what must NOT appear. "No introduction, no summary, no apology, nothing before or after the block" closes off the three places a model most often adds unrequested commentary. A general request for brevity doesn't do this; it just gets you a shorter version of the same preamble.

5. Put the instruction where it survives a long prompt. Instructions stated once at the top of a long prompt compete with everything that follows for attention. Anthropic's own prompting documentation puts it plainly: "Place your long documents and inputs near the top of your prompt, above your query, instructions, and examples." It adds: "Queries at the end can improve response quality by up to 30 percent in tests, especially with complex, multidocument inputs" (Claude prompting best practices, accessed Sep 2, 2026). OpenAI's GPT-4.1 guide draws the same conclusion from the other side: "ideally place your instructions at both the beginning and end of the provided context, as we found this to perform better than only above or below" (GPT-4.1 Prompting Guide, accessed Sep 2, 2026). The two vendors phrase it differently, but neither says pick one end and stop: data goes early, and the instruction that governs the very next answer belongs at the end.

Here's the shape of a specified request, versus a vague one, side by side:

Vague:
Compare these three tools in a table.
Specified:
Compare these three tools in a markdown table.
Columns, in this order: Tool | Starting price/mo | Free tier (Yes/No)
Exactly 3 rows, one per tool, in the order I gave them.
If a value isn't published, write "N/A" — don't estimate it.
No text before or after the table.

Markdown Tables

Tables are for a person to scan, and they fail loudly: a missing column or a blank cell is obvious the moment you look at it. That visibility is the argument for using one whenever you're comparing more than two things.

Present this as a markdown table.
Columns: Name | Category | Value
One row per item, no more than 8 rows.
No prose before or after the table.
Compare these in a table with exactly 4 rows and these columns: Option | Cost | Setup time | Best for.
If a column doesn't apply to a row, write "N/A" — don't leave it blank or invent a value.
Rebuild the table above but sorted by the second column, highest to lowest.
Keep the same columns and the same "N/A" rule.

Tables break down when the things you're comparing don't share the same dimensions, and CSV export, delimiter control, and the empty-cell problem in depth are covered in How to Prompt for Tables and Structured Data.

Formats also combine. A table alone often isn't the full answer; a one-line verdict followed by a short table followed by a checklist covers three different jobs in a single response, and the same specification rules apply to each piece:

Give me your recommendation in one sentence first.
Then a markdown table, columns: Option | Why | Trade-off, one row per option.
Then a checklist of next actions, one per line, each starting with a verb.
No other text between the three sections.

Lists: Plain and Nested

A plain list works when every item is genuinely parallel and order doesn't carry meaning beyond "these are the same kind of thing." A numbered list works when order does matter; a nested list works only when the model can hold the parent-child relationship straight, which gets shakier past two levels.

List these as a plain bulleted list, one item per line.
Each item: a single short phrase, no sub-bullets, no explanation after the item.
Give me this as numbered steps, one action per step, in the order they must happen.
Each step: a single verb-led instruction, under 15 words.
Stop at the last step that's actually necessary — don't pad to a round number.

For a nested list, name the depth limit explicitly, or the model will invent its own:

Structure this as a nested list, maximum 2 levels deep.
Top level: the category, in bold.
Second level: 2-4 sub-items, plain text, no further nesting.
Take the flat list below and group it into a nested list by [category].
Keep every original item; don't summarize or merge any of them.

If you're getting a bulleted list back when you didn't ask for one at all, that's a separate, common failure with its own fix: models default to bullets from training bias and chat-interface habits, not because your prompt asked for them, and Why Does AI Turn Everything into a Bulleted List? covers the exact line that turns it off.

JSON

JSON is for a program to parse, not a person to read, so reach for it only when something downstream will actually consume the response. A missing key or the wrong type breaks a parser in a way an uneven table never breaks a human reader.

Return this as JSON only, matching this shape exactly:
{ "name": "string", "price_usd": number, "in_stock": boolean }
No markdown fences, no explanation text outside the JSON object.
Return JSON matching this exact shape, with these example values:
{ "title": "Example Title", "score": 7, "tags": ["example", "tag"] }
Keep the same keys and types in your answer — only change the values.
If a field has no answer, use null, not an empty string.

Asking nicely still isn't the strongest mechanism available. OpenAI documents its schema-enforced Structured Outputs as a feature that "ensures the model will always generate responses that adhere to your supplied JSON Schema" (Structured model outputs, accessed Sep 2, 2026), a stronger promise than its older JSON mode, which only guarantees syntactic validity. And that older mode has a specific, easy-to-miss requirement worth knowing before you hit it blind: OpenAI's own API reference states that when using JSON mode, "you must also instruct the model to produce JSON yourself via a system or user message," warning that skipping this can make "the model may generate an unending stream of whitespace until the generation reaches the token limit" (openai-openapi specification, accessed Sep 2, 2026) — in practice, this means the word "json" has to appear somewhere in your messages, or the API call errors out entirely rather than silently ignoring the setting. For the full schema syntax, per-field typing, and worked templates by job, see JSON Prompts Explained; for ready-made schemas and exact request bodies per vendor, see the JSON Prompt Generator.

Given the text below, extract it into JSON matching this shape:
{ "sender": "string", "requested_plan": "string", "wants_demo": boolean }
Use only what the text states. If a field isn't mentioned, use null — don't infer it.

CSV

CSV is the format most likely to break silently, because a comma inside a value looks identical to the delimiter separating columns until something downstream tries to parse it and gets one column too many.

Output this as CSV, comma-delimited, with a header row.
Wrap any field containing a comma in double quotes.
One row per item, no blank lines, no text before or after the CSV block.
Same data, but semicolon-delimited instead of comma-delimited, since several fields contain descriptions with commas in them.
Reformat the table above as CSV with these exact column headers: name,category,amount
If a value is missing from the source, write NOT STATED in that field rather than leaving it empty.

The eight distinct reasons a table or CSV comes back misread on the input side, rather than malformed on the way out, are a different problem with its own diagnostic: see Why Does AI Misread My Table or CSV? if you're feeding data in, not asking for it back out.

Headed Prose Sections

When the content genuinely needs paragraphs, not cells, but a reader still needs to skim and jump to one part, headed sections are the format: short H2 or H3 headers a reader scans first, with real prose underneath each one.

Structure this with headers, one per major point.
Each header: under 6 words, phrased as a question if it fits naturally.
Under each header: 2-4 sentences, plain prose, no bullets inside a section.
Reorganize the answer above under these exact headers, in this order: [list your headers].
Move existing content under the matching header rather than rewriting it from scratch.

Getting the content under each header to sound like something a person wrote, rather than a competent AI Overview, is a separate skill from getting the header structure right, and it's covered directly in Why ChatGPT Sounds Generic (And How to Fix It).

A Fixed Template

Sometimes the shape you need isn't a standard format at all, it's a specific fill-in-the-blank document: a bug report, a client update, a product spec. Give the exact template with placeholder labels, not a description of what should be in it.

Fill in this exact template, keeping every label as written:
Summary: [one sentence]
Steps to reproduce: [numbered list, max 5 steps]
Expected result: [one sentence]
Actual result: [one sentence]
Do not add sections. Do not remove sections, even if a section doesn't apply — write "N/A" instead.
Use this template for every item in the list below, repeating the full block per item:
### [Item name]
- Status: [Done / In progress / Blocked]
- Owner: [name]
- Next step: [one short phrase]

A template you reuse across more than a few prompts is worth saving once as a prompt template rather than retyping it each time, which is the entire reason a saved-prompt library exists as a category of tool.

Code Blocks

Asking for a code block isn't just for code. It's also the right ask any time you want the entire answer to be one paste-able, unformatted unit; wrapping a config file, a command, or a snippet of structured text in a fence keeps it from picking up italics or smart quotes on the way through a chat renderer.

Give me the answer as a single code block, language: bash.
Nothing outside the fence — no explanation before or after it.
Rewrite this as one JSON code block, no prose commentary anywhere in the response.
If you need to explain a choice, put it as a comment inside the block using // syntax.
Give me exactly two code blocks: one labeled config.yaml, one labeled .env.
No text between them except a single blank line.

Plain Text, No Formatting at All

This is the format nobody asks for by name, but it's genuinely useful: pasting into an email client that renders literal asterisks and pound signs instead of bold and headers, reading text aloud through a voice interface, or dropping a reply into a plain-text ticketing system where markdown syntax just becomes visual noise. It's also harder to hold onto than any format on this page, because most models default toward structure, not away from it.

Write this as plain text. No markdown: no bullets, no numbered lists, no headers, no bold, no italics.
Write it as continuous paragraphs, not a list of short lines.
Rewrite your last answer with every asterisk, pound sign, and dash-bullet removed.
Where you had a bulleted point, turn it into a full sentence joined with "and" or a comma instead.

The failure mode here is specific: a model will often hold the "no formatting" instruction for the first few hundred words of a long answer, then quietly slip a bullet or a bold phrase back in once the original instruction is several paragraphs behind it. If the answer runs long, restate the constraint partway through, or split the request into shorter turns.

Continue in the same plain-text style as above, still no bullets, still no bold, still one continuous paragraph.

Verified Vendor Structured-Output Modes (Checked Sep 2, 2026)

Everything above is a request written in prose. The three major API providers also offer an enforced mode that constrains what the model can output at the decoding level, which is a categorically different, stronger mechanism, available only through their APIs, not in the consumer chat apps.

ProviderWhat's documented todaySource
OpenAIStructured Outputs (response_format: {"type": "json_schema", ...}) is documented as guaranteeing schema adherence; the older JSON mode only guarantees syntactically valid JSON, and requires the word "json" to appear in your messages or the call errorsStructured model outputs, accessed Sep 2, 2026
Anthropic (Claude)Structured outputs (output_config.format) is out of beta as of this check; the older output_format field and beta header still work during a transition period but the current Python SDK rejects output_format on messages.create()Structured outputs, accessed Sep 2, 2026
Google (Gemini)A response_format field on the POST /v1beta/interactions endpoint enforces a supplied schema; this is a different request shape from the older generationConfig.responseSchema field that still circulates in older tutorialsStructured outputs, Gemini API, accessed Sep 2, 2026

The request itself looks nothing like a prose instruction. Here's the minimal shape of an OpenAI Structured Outputs call, for comparison against every prose snippet on this page:

{
  "model": "gpt-4o-2024-08-06",
  "messages": [{ "role": "user", "content": "Extract the name and price." }],
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "extraction",
      "strict": true,
      "schema": { "type": "object", "properties": { "name": {"type": "string"}, "price": {"type": "number"} }, "required": ["name", "price"] }
    }
  }
}

Two things worth flagging honestly rather than smoothing over. First, none of this reaches a consumer chat window: if you're typing into ChatGPT, Claude.ai, or Gemini directly rather than calling an API, none of these modes are available to you, and the prose techniques earlier on this page are the actual ceiling. Second, these interfaces move: Anthropic's own migration note in its current docs says its output_format parameter "has moved to output_config.format," which means content written against the older shape has already gone stale once. Check the vendor's current page before shipping code against any of these three, rather than trusting a screenshot from an older tutorial, including this one after enough time has passed.

For the deeper mechanics of why a plain-language format request gets ignored in the first place, buried instructions, conflicting instructions, an earlier example showing the wrong shape, and a walkthrough of each enforced mode, Why Does AI Ignore My Format Instructions? covers the causal side this page doesn't re-litigate.

Putting It Together

Format is one slot in a prompt's overall structure, alongside role, task, and constraints; if you want the fuller structure this instruction slots into, ChatGPT Prompt Structure Explained (Role, Task, Format, Constraints) covers where format fits alongside the rest. On this page specifically: pick the shape, show a worked example of it, name every key or column, decide the literal placeholder for "unknown" before you ask, forbid the specific commentary you don't want, and put the instruction where it survives the length of your prompt. None of that guarantees compliance on every single run. It gets you close enough, often enough, that the failures become the exception you notice rather than the norm you fight.

Free Chrome Extension

Stop rewriting prompts. Start shipping.

Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 4.8★ on the Chrome Web Store.

Create An Account

Frequently asked questions

Free Chrome Extension

Stop rewriting prompts. Start shipping.

Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 4.8★ on the Chrome Web Store.

Create An Account