Claude API CSV Data Extraction Example
If you need a Claude API CSV data extraction example that actually works on messy, real-world files, the short answer is: send the CSV content (or a representative chunk of it) as text in your message, pair it with a schema-constrained prompt or a tool definition, and ask Claude to return structured JSON. Claude handles inconsistent delimiters, merged headers, free-text fields, and mixed data types far better than regex or traditional parsers because it reasons about meaning, not just position.
This matters because most "CSV extraction" problems aren't really about parsing commas — they're about interpreting ambiguous, human-generated data: a notes column that sometimes contains a phone number, a date column with three different formats, or a spreadsheet exported from a CRM where column order changes month to month. Below is a working pattern you can copy, plus the tool-use variant for when you want guaranteed JSON output.
The basic pattern: prompt + raw CSV text
For files under a few thousand rows, the simplest approach is to paste the CSV directly into the prompt and ask for structured output.
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"messages": [{
"role": "user",
"content": "Extract the following fields from this CSV into a JSON array: name, email, company, signup_date (ISO 8601). Skip rows missing an email. Return only JSON.\n\n"
+ "name,contact,org,signed_up\nJane Doe,jane@acme.com,Acme Inc,03/14/2024\nBob,bob at widgets.io,Widgets Co,2024-01-05\n"
}]
}'
Claude will normalize bob at widgets.io into a valid-looking email if it can infer intent, standardize both date formats to ISO 8601, and skip rows that don't qualify — all in one pass. This is the core value of using an LLM for extraction instead of writing custom parsing rules for every CSV variant you encounter.
Why this beats traditional parsing for messy data
Classic CSV parsers (pandas, csv module, etc.) are excellent at splitting rows and columns but know nothing about semantics. They can't tell you that Qty and quantity_ordered mean the same thing, or that a status column using "Y", "yes", and "1" interchangeably should all map to true. Claude can handle that normalization as part of the extraction step, which is especially useful when ingesting CSVs from multiple sources with no shared schema.
Enforcing a strict schema with tool use
If you need guaranteed structure (for example, writing straight into a database), don't rely on prompt instructions alone — use Claude's tool-calling feature to force the output into a defined JSON schema.
{
"name": "extract_rows",
"description": "Extract structured records from CSV text",
"input_schema": {
"type": "object",
"properties": {
"records": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"email": { "type": "string" },
"company": { "type": "string" },
"signup_date": { "type": "string", "format": "date" }
},
"required": ["name", "email"]
}
}
},
"required": ["records"]
}
}
Send this tool definition alongside your message, and Claude will return a tool call with input.records matching the schema exactly — no markdown fences, no explanatory text to strip out. This is the most reliable way to pipe CSV extraction straight into downstream code.
Handling larger CSV files
For files that exceed a comfortable context size, chunk by rows (not by raw character count, to avoid splitting a row mid-line) and process each chunk independently. A simple strategy:
- Parse the CSV with a lightweight library just to split rows reliably.
- Batch 200–500 rows per request, keeping the header row in every batch for context.
- Send each batch with the same extraction prompt or tool schema.
- Concatenate the resulting JSON arrays.
const rows = csvText.split("\n");
const header = rows[0];
const chunks = [];
for (let i = 1; i < rows.length; i += 300) {
chunks.push([header, ...rows.slice(i, i + 300)].join("\n"));
}
Run chunks in parallel for speed, but watch your rate limits — this is where request volume adds up quickly if you're calling the Anthropic API directly.
Running this in production
Prototyping CSV extraction in a notebook is easy. Running it reliably in a product — with retries, streaming for large responses, usage tracking per customer, and API keys you can rotate without touching Anthropic's dashboard — is a different problem. That's the gap SubToAPI fills: it sits on top of your existing Claude access and gives you a standard HTTPS API with sub_live_... keys, so your extraction pipeline doesn't need to manage Anthropic credentials directly.
A typical production call looks like this:
curl https://api.subtoapi.app/v1/messages \
-H "Authorization: Bearer $SUBTOAPI_KEY" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Extract rows as JSON: ..."}]
}'
Same request shape as the direct Anthropic API, but with team seats, per-key usage metadata, and streaming support already built in — useful if several engineers or services are all hitting the same CSV extraction endpoint. See the quickstart to get a key, or the messages docs for the full request reference. If your extraction jobs are large, streaming avoids timeouts on bigger responses, and the tools docs cover schema enforcement in more depth.
Common pitfalls
- Don't skip validation. Even with a strict schema, validate dates, emails, and numeric ranges after extraction — Claude follows instructions well but isn't a database constraint.
- Keep headers in every chunk. If you split a large CSV, always include the header row so column meaning isn't lost mid-file.
- Be explicit about null handling. State clearly what to do with missing values ("leave empty string" vs "omit the field") to avoid inconsistent output across chunks.
questions
Can Claude extract data from CSVs with inconsistent column names across files? Yes — describe the target schema in your prompt or tool definition and Claude will map varying source column names (e.g., Qty vs quantity) to your canonical fields based on meaning, not exact string match.
What's the best way to get guaranteed valid JSON from CSV extraction? Use tool use / function calling with a strict input_schema rather than asking for JSON in plain text. This removes the need to strip markdown or handle malformed output.
How do I handle CSV files too large for one request? Chunk by rows while keeping the header in each chunk, send chunks as separate requests (in parallel if your rate limits allow), and merge the resulting JSON arrays afterward.