Use Citations

Su Suriya Ravichandran Updated 10 Nov 2026
6 min read ·Lesson 157 of 200

Answers That Point to Their Sources

An answer built from documents is only as trustworthy as the reader's ability to check it. A sentence that says "refunds are available within fourteen days" is useful, but a reader who wants to confirm it needs to find the passage it came from. Citations provide that link. When citations are enabled, Claude attaches to each claim a reference to the exact passage it relied on, identified by its document and its position, along with the quoted text. The application can then show the source next to the claim, and verify it.

Lesson 155 introduced citations for web search. This lesson covers the same mechanism for documents you supply: plain text documents, PDFs, and search result blocks that your own retrieval system produces. The principle is identical. The answer carries evidence, and the evidence can be checked.


Enabling Citations on a Document

A document block accepts a citations setting. When it is enabled, Claude's answers can include citations that refer to that document:

document = {
    "type": "document",
    "title": "Refund policy",
    "source": {"type": "text", "media_type": "text/plain", "data": POLICY_TEXT},
    "citations": {"enabled": True},
}

response = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": [
        document,
        {"type": "text", "text": "How long do customers have to request a refund?"},
    ]}],
)

The document is the source, and the question follows it, as in Lessons 114 and 124. The citations setting belongs on the document block, not on the question.

Citations have restrictions that matter for design. According to the documentation, they cannot be combined with structured outputs, because a citation requires text blocks to be interleaved with citation references, which conflicts with a strict JSON schema, and the API returns an error in that case. For extracting structured data with a citation for each value, the documentation describes a separate approach. Citations also apply to whole documents, and a citation cannot point to part of a block that the API does not expose as citable.


Kinds of Location

A citation names where its evidence lies, and the form depends on the source. For plain text documents, the location is a character range. For PDFs, it is a page range. For search result blocks, it is a block index. Each form includes the cited text, so the reader sees the quotation as well as the location:

SourceLocation typeWhat it records
Plain text documentchar_locationThe start and end character positions, and the text
PDFpage_locationThe page numbers, and the text
Search result blocksearch_result_locationThe block index and the text
Web search (Lesson 155)web_search_result_locationThe URL, the title, and the text

The positions are what make verification possible. A citation says "the words between position 0 and position 49 of this document are the evidence", and a check can confirm that the words at those positions are the words cited.


Verifying Citations

Citations are produced by the model, so an application should not trust them blindly. The check is simple for character locations: the text at the stated positions must equal the cited text. A mismatch means the citation is wrong, and the answer should be flagged, not shown with false confidence.

The verifier below applies that check. It builds two citations for a short policy, one correct and one that quotes the right sentence with the wrong words, and reports each result:

"""citations_check.py: verify that each citation's text appears at its stated position."""

POLICY = ("Refunds are available within 14 days of purchase. "
          "Certificates are issued within 24 hours of passing the final quiz.")


def check_citation(citation: dict, documents: dict[str, str]) -> str:
    source = documents.get(citation["document_title"])
    if source is None:
        return "unknown document"
    start, end = citation["start_char_index"], citation["end_char_index"]
    if source[start:end] != citation["cited_text"]:
        return "cited text does not match the stated span"
    return "ok"


if __name__ == "__main__":
    documents = {"Refund policy": POLICY}
    first = "Refunds are available within 14 days of purchase."
    second = "Certificates are issued within 24 hours of passing the final quiz."

    good = {"type": "char_location", "document_title": "Refund policy",
            "start_char_index": POLICY.index(first),
            "end_char_index": POLICY.index(first) + len(first), "cited_text": first}
    bad = {"type": "char_location", "document_title": "Refund policy",
           "start_char_index": POLICY.index(second),
           "end_char_index": POLICY.index(second) + len(second),
           "cited_text": "Certificates are issued within 48 hours."}

    print("citation 1:", check_citation(good, documents))
    print("citation 2:", check_citation(bad, documents))

Output:

citation 1: ok
citation 2: cited text does not match the stated span

How It Works

  1. The document is looked up by title, so a citation that names an unknown document is caught before any position is checked.
  2. The check compares the slice with the cited text. The span source[start:end] is the exact text at the stated position, and it must equal what the citation says it quotes.
  3. The first citation passes, because its positions were computed from the actual sentence, and its cited text is that sentence.
  4. The second citation points to the right place but quotes wrong words, so the slice differs from the cited text, and the check reports the mismatch. This is the kind of error a model can make when it paraphrases while citing.
  5. The positions in the demonstration come from index(), which is how a real pipeline records positions when it prepares its documents. Keeping a record of positions with the document makes verification possible later.

Citations and Retrieval Systems

Many applications find the relevant passages with their own search, and then ask Claude to answer from them. Those passages can be supplied as search_result blocks, each with its own citation setting, and Claude cites them by block index. The documentation notes that all search results in one request must share the same citation setting. Mixing enabled and disabled results produces an error, so a retrieval layer should apply one setting consistently.

The citation then points to the passage the retrieval system chose, which connects the answer to the search results rather than to the whole corpus. This is the form Lesson 99's search tool would take if it were combined with citations.


Citations in Caching

Document blocks that carry citations can be cached, like any document block (Lesson 124). The citation setting is part of the block, so changing it invalidates the cache entry for that document. A knowledge base served to many users benefits from caching, provided its citation settings are stable.


Summary

Citations attach to each claim a reference to the passage it came from, with its location and its cited text. They can be enabled on document blocks and on search results, with restrictions that include incompatibility with structured outputs and the all-or-nothing rule for search results. Because citations are produced by the model, an application should verify them against the source, and treat mismatches as errors. The next lesson turns to a practical question that comes before many requests: how many tokens they will use.

0 Comments

Reviewed before they appear

No comments yet.

Anthropic SDK Using Python
Anthropic SDK Intro Claude API Intro SDK Requirements Install Anthropic SDK Upgrade the SDK Create an API Key Set API Keys Use Environment Variables Import Anthropic Create a Client Send Your First Message Choose a Claude Model Set Max Tokens Read a Response Print Response Text Understand Message Blocks Use System Prompts Send User Messages Set Temperature Handle Stop Reasons Messages API Intro Create Messages Use Message Roles Send Conversation History Continue a Conversation Build a Chat Loop Reset Chat History Use Multiple Turns Inspect Message IDs Read Usage Data Write Clear Prompts Set a System Prompt Add Context to Prompts Use Prompt Templates Add Examples to Prompts Request JSON Output Use XML Tags Control Response Length Improve Prompt Quality Avoid Prompt Injection Read Text Blocks Read Content Blocks Check Stop Reasons Count Input Tokens Count Output Tokens Count Tokens Before Sending Limit Output Tokens Use Stop Sequences Read Request IDs Parse API Responses Streaming Intro Stream Text Output Use Stream Events Use Stream Helpers Get Final Messages Stream Async Responses Handle Stream Errors Build a Live Chat Stream Long Responses Close Streams Safely Build a Chatbot Keep Chat History Manage Chat Sessions Add Chat Memory Build a CLI Chatbot Build a Web Chatbot Use Flask with Claude Use FastAPI with Claude Return JSON from an API Add Chat Error Messages Async SDK Intro Create an Async Client Send Async Messages Use asyncio Run Parallel Requests Stream Async Text Handle Async Errors Set Async Timeouts Close Async Clients Choose Sync or Async Tool Use Intro Define a Tool Create Tool Schemas Send Tools to Claude Read Tool Calls Run Python Tools Return Tool Results Continue After Tool Use Control Tool Choice Handle Tool Errors Use the beta_tool Decorator Create a Tool Runner Add Tool Docstrings Validate Tool Inputs Use Multiple Tools Limit Tool Calls Log Tool Activity Build a Weather Tool Build a Search Tool Build a Calculator Tool Structured Output Intro Request JSON Data Validate JSON Output Use Pydantic Models Handle Invalid JSON Extract Fields from Text Generate Typed Data Use Image URLs Send Base64 Images Read PDFs with Claude Use Output Schemas Build Data Extraction Test Structured Responses Send Image Inputs Upload Files Use File IDs Process Text Files Summarize Documents Extract Table Data Handle File Errors Read Cache Usage Reduce Repeated Input Costs Debug Cache Misses Prompt Caching Intro Enable Prompt Caching Cache System Prompts Cache Long Context Test Cache Performance Use Cache Breakpoints Cache Best Practices Message Batches Intro Create a Message Batch Set Batch IDs Check Batch Status List Message Batches Get Batch Results Process Batch Outputs Handle Failed Batch Items Use Batches for Bulk Tasks Compare Batches and Requests Handle API Errors Handle Rate Limits Retry Failed Requests Set Request Timeouts Handle Network Errors Use Exponential Backoff Build Reliable API Calls Use Extended Thinking Log API Errors Track Request IDs Paginate API Results Set Thinking Budgets Read Thinking Blocks Use Tool Search Use Web Search Tools Use Computer Tools Use Citations Use Token Counting Read Raw Responses Set Custom Headers Use Claude on AWS Bedrock Use Claude on Vertex AI Use Claude on Microsoft Foundry Configure Cloud Credentials Choose a Cloud Provider Compare API Integrations Configure Provider Clients Handle Cloud Errors Use Cloud SDK Extras Deploy Cloud Apps Protect API Keys Use a .env File Ignore Secrets in Git Validate User Input Reduce Prompt Injection Limit Tool Permissions Avoid Unsafe Tool Calls Sanitize Tool Results Set Usage Limits Review Security Logs Test SDK Functions Mock API Responses Test Error Handling Test Streaming Code Measure Token Usage Track API Costs Configure Logging Deploy with Docker Deploy a FastAPI App Monitor Production Apps Build a Claude Chatbot Build a Text Summarizer Build a Code Explainer Build a JSON Extractor Build a PDF Assistant Build a Streaming Chat App Build a Tool-Calling Agent Build a Batch Processor Build a Research Assistant Build a Claude API Dashboard
Ask about this post
AI Ask about this post

Ask questions about Use Citations and get answers drawn from it.

Signed-in readers only.