How to Batch-Generate Product Descriptions with Claude and the Anthropic Batch API
Use Anthropic’s Batch API with Claude 3.5 Sonnet to generate hundreds of SEO product descriptions at 50% off standard pricing. Step-by-step tutorial.
At some point, every e-commerce operator hits the same wall: you’ve got 400 SKUs, three seasonal lines dropping next month, and a copywriter who just quoted you $8 per description. The math gets ugly fast. AI tools promise to fix this, but most tutorials show you how to write one product description at a time — which is great for demos and useless for actual catalogs.
Anthropic’s Batch API is the piece people miss. Instead of firing off API calls one by one and paying standard rates for each, you bundle your entire product list into a single batch job, submit it, and get results back within 24 hours at 50% of the standard API price. The trade-off is that it’s not instant — but if you’re generating descriptions for 200 winter jackets, you don’t need them in five minutes. You need them accurate, consistent, and cheap. That’s exactly what this does.
This tutorial walks through the complete setup: structuring your product data, writing prompts that actually produce good copy (not AI word-salad), submitting a batch job, retrieving results, and building a repeatable workflow you can run for every new product drop.
What You’ll Actually Achieve
By the end of this, you’ll have a working pipeline that takes a spreadsheet of product data and returns a matching set of SEO-optimized, brand-consistent descriptions — at half the cost of regular API usage. The workflow runs asynchronously, meaning you submit the job, do other things, and pull results when they’re ready. No babysitting required.
The current model to use is Claude 3.5 Sonnet (released October 2024, model ID: claude-3-5-sonnet-20241022). There is no Claude Sonnet 4.6 — anyone telling you otherwise is either confused or selling something. Stick with what’s documented and available.
What You Need Before Starting
You need an Anthropic API key (get one at console.anthropic.com), basic familiarity with Python or JavaScript, and your product data in a structured format — CSV works fine as a starting point. You don’t need to be a developer, but you do need to be comfortable running a script and reading JSON output. If you can copy-paste code and edit variable names, you’re qualified.
Step 1 — Structure Your Product Data
The quality of your output is ceiling-capped by the quality of your input. A prompt that just says “write a description for a blue jacket” will produce generic slop. A prompt that includes product name, material, key features, target customer, brand tone, and SEO keywords will produce something actually usable. Before writing a single line of code, get your data organized.
Your CSV should have columns for: product name, category, materials/ingredients, key features (3-5 bullet points), price point, target audience, and any brand-specific terms you always use or always avoid. This takes time upfront, but it’s what separates “AI wrote this and it shows” from copy that actually converts.
Pro tip ✅
Add a “tone” column to your CSV. Different product lines often need different voices — rugged and technical for outdoor gear, soft and aspirational for skincare. One column, big impact on output consistency.
Step 2 — Write Your Core Prompt Template
Your prompt is doing heavy lifting here. It runs for every single product, so every word in the template matters. Here’s a production-ready base prompt that you’ll customize per your brand:
You are a senior e-commerce copywriter for a [BRAND_TONE] brand. Write a product description for the following item.
Product: {product_name}
Category: {category}
Materials: {materials}
Key features: {features}
Price point: {price}
Target customer: {target_audience}
Requirements:
- Length: 80-120 words
- Open with a benefit-led hook sentence (not the product name)
- Include all key features naturally in prose — no bullet lists
- End with a subtle call to action
- Tone: [BRAND_TONE] — confident, specific, never fluffy
- Naturally include these SEO keywords: {seo_keywords}
- Do NOT use the words: luxurious, stunning, amazing, perfect, revolutionary
Output ONLY the product description. No headers, no commentary, no quotation marks.
The “Output ONLY” instruction at the end is critical for batch processing. When you’re parsing hundreds of responses, you don’t want to strip preamble text from each one. The model should return clean copy, nothing else. The banned words list is also worth customizing — pull whatever your brand guidelines explicitly exclude and put it here.
Here’s a variant for fashion specifically:
You are writing for a contemporary fashion brand with a dry, editorial voice — think Everlane meets early-era Acne Studios. No exclamation marks. No "perfect for" constructions.
Product: {product_name}
Fabric: {materials}
Fit: {fit_description}
Available in: {colorways}
Key details: {features}
Season: {season}
Price: {price}
Write a product description of 70-100 words. Lead with what makes the garment worth owning. Mention fabric and fit specifically. Close with one concrete styling note. No filler. Output only the description.
And one for skincare/beauty, where ingredient storytelling matters:
Write a product description for the following skincare item. The brand voice is clean, science-informed, and direct — we explain what ingredients do, not just list them.
Product: {product_name}
Key ingredients: {ingredients}
Skin concerns addressed: {concerns}
Texture/format: {texture}
How to use: {usage}
Key claim: {hero_claim}
Write 90-110 words. Open by naming the primary skin concern this solves. Explain the hero ingredient's function in one sentence. Describe texture and application experience. Close with the expected result. No jargon. No promises that require clinical backing. Output only the description.
Pro tip ✅
Run your prompt template against 5-10 products manually via the regular API before building the batch. Catch prompt issues when they cost you five minutes, not five hours of batch output to regenerate.
Step 3 — Build the Batch Request File
The Batch API takes a JSONL file (JSON Lines — one JSON object per line) where each line is a complete API request with a unique custom ID. Here’s the structure for a single request in that file:
{
"custom_id": "product-SKU-0042",
"params": {
"model": "claude-3-5-sonnet-20241022",
"max_tokens": 300,
"messages": [
{
"role": "user",
"content": "You are a senior e-commerce copywriter...[your full prompt with product data substituted in]"
}
]
}
}
The custom_id field is your lifeline when you retrieve results. Name it something that maps back to your product database — a SKU, a product ID, anything that lets you match output to input automatically. If you name them product-1, product-2, etc., you’ll spend an annoying afternoon manually re-linking descriptions to products. Don’t do that to yourself.
Here’s a Python script to generate the JSONL from your CSV:
import csv
import json
PROMPT_TEMPLATE = """You are a senior e-commerce copywriter for a [YOUR BRAND TONE] brand. Write a product description.
Product: {product_name}
Category: {category}
Materials: {materials}
Key features: {features}
Target customer: {target_audience}
SEO keywords: {seo_keywords}
Requirements:
- 80-120 words
- Benefit-led opening
- Natural prose (no bullet lists)
- Subtle CTA at end
- Tone: confident, specific, no fluff
- Do NOT use: luxurious, stunning, amazing, perfect
Output ONLY the product description."""
batch_requests = []
with open("products.csv", "r") as f:
reader = csv.DictReader(f)
for row in reader:
prompt = PROMPT_TEMPLATE.format(
product_name=row["product_name"],
category=row["category"],
materials=row["materials"],
features=row["key_features"],
target_audience=row["target_audience"],
seo_keywords=row["seo_keywords"]
)
request = {
"custom_id": f"product-{row['sku']}",
"params": {
"model": "claude-3-5-sonnet-20241022",
"max_tokens": 300,
"messages": [{"role": "user", "content": prompt}]
}
}
batch_requests.append(request)
with open("batch_input.jsonl", "w") as f:
for req in batch_requests:
f.write(json.dumps(req) + "n")
print(f"Generated {len(batch_requests)} batch requests")
Warning ⚠️
Max tokens of 300 is generous for a 120-word description but not wasteful. Setting it too low risks truncated outputs mid-sentence — and truncated product copy is worse than no copy at all. Check your longest expected output and set max_tokens accordingly.
Step 4 — Submit the Batch Job
Once you have your JSONL file, submitting the batch is three API calls: upload the file, create the batch, check status. Here’s the complete submission script:
import anthropic
client = anthropic.Anthropic(api_key="your-api-key-here")
# Submit the batch
with open("batch_input.jsonl", "rb") as f:
batch = client.beta.messages.batches.create(
requests=json.load(f) # or pass the parsed list directly
)
print(f"Batch ID: {batch.id}")
print(f"Status: {batch.processing_status}")
print("Save this batch ID — you'll need it to retrieve results.")
# Check status (run this separately after waiting)
batch_status = client.beta.messages.batches.retrieve(batch.id)
print(f"Status: {batch_status.processing_status}")
print(f"Completed: {batch_status.request_counts.succeeded}")
print(f"Errors: {batch_status.request_counts.errored}")
The batch processes within 24 hours. In practice, smaller batches (under a few hundred requests) often finish much sooner, but don’t architect your workflow around that assumption. Plan for 24 hours and be pleasantly surprised when it’s faster.
Step 5 — Retrieve and Parse Results
When the batch status shows ended, pull your results and map them back to your product catalog:
import anthropic
import json
import csv
client = anthropic.Anthropic(api_key="your-api-key-here")
BATCH_ID = "msgbatch_your_batch_id_here"
# Retrieve results
results = {}
for result in client.beta.messages.batches.results(BATCH_ID):
if result.result.type == "succeeded":
description = result.result.message.content[0].text
results[result.custom_id] = description
else:
results[result.custom_id] = f"ERROR: {result.result.error.type}"
# Write to output CSV
with open("product_descriptions_output.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["sku", "description", "status"])
for custom_id, description in results.items():
sku = custom_id.replace("product-", "")
status = "error" if description.startswith("ERROR") else "ok"
writer.writerow([sku, description, status])
print(f"Retrieved {len(results)} results")
error_count = sum(1 for d in results.values() if d.startswith("ERROR"))
print(f"Errors: {error_count} — review and resubmit these individually")
Pro tip ✅
Always check your error count before importing to your store. A 2% error rate across 500 products is 10 blank or broken descriptions. Pull those SKUs, check why they failed (often a malformed input field), fix the data, and resubmit just those ones via the regular API.
Step 6 — Quality Check Before You Ship
Resist the urge to dump all 500 descriptions directly into your CMS. Run a quick sanity pass first. Sample 10-15 outputs across different product categories and check for: descriptions that hit the wrong tone, outputs where a variable substitution clearly failed (you’ll see placeholder text or oddly generic sentences), SEO keywords stuffed in awkwardly, and anything that’s technically accurate but sounds like it was written by someone who has never used the product.
The fix for most quality issues isn’t rewriting individual descriptions — it’s improving your prompt template and rerunning the batch for the problematic category. Batch API makes iterating on prompt quality cheap. Use that to your advantage.
Note 💡
Claude 3.5 Sonnet handles long, detailed prompts well. If your quality is inconsistent across a category, the fix is almost always adding more specific context to the prompt — not switching models or adding post-processing steps.
The Actual Cost Breakdown
Anthropic charges Batch API requests at 50% of standard API pricing. The exact cost depends on how many input tokens your prompts consume and how long the outputs are. A detailed prompt template plus product data typically runs 200-400 input tokens per product; a 120-word output is roughly 160 tokens. At current Claude 3.5 Sonnet pricing with the batch discount, generating a few hundred descriptions costs a few dollars at most — exact figures depend on current pricing at console.anthropic.com, which you should check before budgeting.
The honest comparison isn’t AI cost vs. human copywriter cost — it’s AI cost plus your time to set this up, QA outputs, and handle edge cases. The first batch takes a few hours to configure correctly. The fifth batch takes twenty minutes. That’s where the real efficiency shows up: repeatability. Every new product drop, you update the CSV, run the script, wait for results, do a quick QA pass, and you’re done.
Avoid 🚫
Don’t skip the human QA step to save time. AI-generated copy that’s slightly off-brand or contains a subtle factual error about a product will cost you more in customer confusion and returns than the twenty minutes of review you skipped. Automate the generation; keep humans on quality gate.
Make It a Repeatable System
The workflow described here scales to any catalog size. The scripts don’t care if you submit 50 products or 5,000. Add a simple scheduler — even a cron job — to automatically kick off a new batch whenever your product database gets new SKUs flagged as “description pending,” and you’ve got an always-on content pipeline that runs without anyone managing it day-to-day.
The 24-hour processing window is a feature, not a bug, if you plan around it. New products added Monday morning have descriptions ready Tuesday. That’s a reasonable production cadence for most e-commerce operations, and it costs a fraction of what you’d pay to rush a freelancer for the same turnaround.
The brands that will get the most out of this aren’t the ones chasing the cheapest output — they’re the ones who spend time on their prompt templates, maintain clean product data, and treat AI as one step in a workflow rather than the whole workflow. That’s the actual difference between catalog copy that reads like copy and catalog copy that reads like it was written by someone who understood the product.


