← Blog

Claude API Sentiment Analysis: Implementation Guide

2026-11-08 · 5 min read · SubToAPI Team

Sentiment analysis with the Claude API means sending text to a language model and getting back a structured judgment — positive, negative, neutral, or something more nuanced — instead of training and maintaining your own classifier. This guide walks through the actual implementation: how to design the prompt, how to force consistent structured output, how to handle mixed or sarcastic sentiment, and how to scale the approach once you're processing thousands of reviews, tickets, or social posts a day.

If you've only used off-the-shelf sentiment libraries before, the main shift is that you're no longer limited to three fixed labels. Claude can score intensity, detect sarcasm, extract the specific aspect being praised or criticized, and explain its reasoning — all from a single prompt, without retraining anything when your requirements change.

Why use an LLM instead of a traditional classifier

Traditional sentiment models (VADER, TextBlob, fine-tuned BERT) are fast and cheap but brittle. They struggle with domain-specific language, sarcasm, and multi-aspect text ("the food was great but the service was terrible"). Claude handles all three out of the box because it's reasoning over meaning, not matching keyword lists.

The trade-off is latency and cost per request compared to a local model. For most products — support ticket analysis, product review mining, social listening, survey processing — this trade-off is worth it, especially since you can batch requests and cache prompts to keep costs predictable.

Designing the prompt

The biggest implementation mistake is asking an open-ended question like "what's the sentiment of this text?" and parsing free-form prose. That's slow to build and fragile to maintain. Instead, constrain the output format explicitly.

A solid baseline prompt:

You are a sentiment classification system. Analyze the text below and respond with ONLY valid JSON matching this schema:

{
  "sentiment": "positive" | "negative" | "neutral" | "mixed",
  "confidence": number between 0 and 1,
  "intensity": number between 1 and 5,
  "aspects": [{"topic": string, "sentiment": string}]
}

Text: "{{user_text}}"

This gets you a usable baseline, but system prompts alone don't guarantee valid JSON every time. For production systems, use Claude's tool use feature instead — it enforces a schema at the API level rather than relying on the model following instructions in plain text.

Using tool use for guaranteed structure

Defining a tool with a strict input schema is the most reliable way to get consistent sentiment output. Here's a generic example against the Claude Messages API:

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": 300,
    "tools": [{
      "name": "record_sentiment",
      "description": "Record the sentiment analysis result for a piece of text",
      "input_schema": {
        "type": "object",
        "properties": {
          "sentiment": {"type": "string", "enum": ["positive", "negative", "neutral", "mixed"]},
          "confidence": {"type": "number"},
          "intensity": {"type": "integer", "minimum": 1, "maximum": 5},
          "reasoning": {"type": "string"}
        },
        "required": ["sentiment", "confidence", "intensity"]
      }
    }],
    "tool_choice": {"type": "tool", "name": "record_sentiment"},
    "messages": [{
      "role": "user",
      "content": "Analyze: \"Shipping took forever but the product itself is fantastic.\""
    }]
  }'

Forcing tool_choice to the specific tool guarantees Claude returns structured arguments rather than prose. Your application code just reads tool_use.input — no regex, no JSON.parse failures on malformed output.

If you're routing this through SubToAPI instead of managing raw Anthropic credentials, the request shape is identical — you just point at your SubToAPI endpoint and key:

const response = await fetch("https://api.subtoapi.app/v1/messages", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    model: "claude-sonnet-4-5",
    max_tokens: 300,
    tools: [/* same tool definition as above */],
    tool_choice: { type: "tool", name: "record_sentiment" },
    messages: [{ role: "user", content: reviewText }]
  })
});

This matters when sentiment analysis is one feature inside a larger product — you get a single sub_live_... key, per-key usage metadata, and team seats, so you're not juggling separate billing and rate limits for every teammate or environment hitting the model. See /docs/tools for the full tool use reference and /docs/messages for the base request format.

Handling mixed sentiment and aspect-level analysis

Real-world text rarely falls cleanly into one bucket. "Mixed" as a top-level label is useful, but for product feedback you usually want aspect-level breakdowns — sentiment per topic mentioned (price, support, UI, delivery). Add an aspects array to your tool schema and let Claude populate it per mention. This is far more useful for downstream reporting than a single score, and it's the kind of nuance keyword-based tools can't produce reliably.

For sarcasm and tone shifts, give Claude more context, not less. A one-line prompt with no surrounding context will mis-score sarcastic praise ("oh great, another outage") as positive more often than a prompt that includes the source — a support ticket, a product review, a tweet reply — since tone conventions differ by channel.

Batching and scaling the pipeline

Once the single-request flow works, the implementation challenge becomes throughput and cost:

If you're building this as part of a larger internal tool or customer-facing product, start from /docs/quickstart to get a key issued and your first request working, then move to /docs/streaming if you need to surface sentiment results incrementally in a UI rather than waiting for a full batch to complete. Plans start at /pricing with a free trial at /signup, which is usually enough to validate your prompt and schema before committing to a paid tier.

questions

Is Claude API sentiment analysis accurate enough for production use? For general positive/negative/neutral classification, yes — accuracy is typically higher than keyword-based tools, especially on sarcasm and domain-specific language. For regulated or high-stakes decisions, pair model output with a human review step rather than fully automating action on the result.

Should I use tool use or plain prompting for structured sentiment output? Use tool use with a strict input_schema and tool_choice set to that tool. Plain prompting with JSON instructions works for prototypes but occasionally produces malformed output that breaks downstream parsing at scale.

How much does running sentiment analysis at scale cost? Cost depends on text length and volume, not a fixed per-call fee. Keep requests short, cache repeated system prompts, and batch texts where latency allows — these three changes typically cut cost per analyzed item by more than half compared to naive one-text-per-request calls.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →