← Back to daily report

build-with-claude/working-with-messages.md

Changed on 2026-08-31 18:18:30 EST

+1 lines added
-1 lines removed
Visual Diff
---¶
title: Using the Messages API¶
url: https://platform.claude.com/docs/en/build-with-claude/working-with-messages¶
description: Practical patterns and examples for using the Messages API effectively¶
---¶

Anthropic offers two ways to build with Claude, each suited to different use cases:¶

| | Messages API | Claude Managed Agents |¶
| -------------- | ------------------------------------------- | ------------------------------------------------------------------------- |¶
| **What it is** | Direct model prompting access | Pre-built, configurable agent harness that runs in managed infrastructure |¶
| **Best for** | Custom agent loops and fine-grained control | Long-running tasks and asynchronous work |¶

This guide covers common patterns for working with the Messages API, including basic requests, multi-turn conversations, prefill techniques, and vision capabilities. For complete API specifications, see the [Messages API reference](https://platform.claude.com/docs/en/api/messages/create). For the managed agent harness instead, see the [Claude Managed Agents overview](https://platform.claude.com/docs/en/managed-agents/overview).¶

<Note>¶
ForTo learn how zero data retention (ZDR) applies to this feature, see [API and data retention](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention).¶
</Note>¶

## Basic request and response¶

<Note>¶
The `temperature`, `top_p`, and `top_k` sampling parameters are not supported on Claude 4.7 and later models and Claude Mythos Preview. Setting them to a non-default value returns a 400 error. Omit them from request payloads and use prompting to guide the model's behavior instead. See the [migration guide](https://platform.claude.com/docs/en/models/opus-5/migration-guide#migrating-from-claude-opus-47).¶
</Note>¶

<CodeGroup>¶
```bash cURL¶
#!/bin/sh¶
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-opus-5",¶
"max_tokens": 1024,¶
"messages": [¶
{"role": "user", "content": "Hello, Claude"}¶
]¶
}'¶
```¶

```bash CLI¶
ant messages create \¶
--model claude-opus-5 \¶
--max-tokens 1024 \¶
--message '{role: user, content: "Hello, Claude"}'¶
```¶

```python Python¶
message = anthropic.Anthropic().messages.create(¶
model="claude-opus-5",¶
max_tokens=1024,¶
messages=[{"role": "user", "content": "Hello, Claude"}],¶
)¶
print(message)¶
```¶

```typescript TypeScript¶
const anthropic = new Anthropic();¶

const message = await anthropic.messages.create({¶
model: "claude-opus-5",¶
max_tokens: 1024,¶
messages: [{ role: "user", content: "Hello, Claude" }]¶
});¶
console.log(message);¶
```¶

```csharp C#¶
AnthropicClient client = new();¶

var parameters = new MessageCreateParams¶
{¶
Model = Model.ClaudeOpus5,¶
MaxTokens = 1024,¶
Messages = [new() { Role = Role.User, Content = "Hello, Claude" }]¶
};¶
var message = await client.Messages.Create(parameters);¶
Console.WriteLine(message);¶
```¶

```go Go¶
client := anthropic.NewClient()¶

response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{¶
Model: anthropic.ModelClaudeOpus5,¶
MaxTokens: 1024,¶
Messages: []anthropic.MessageParam{¶
anthropic.NewUserMessage(anthropic.NewTextBlock("Hello, Claude")),¶
},¶
})¶
if err != nil {¶
log.Fatal(err)¶
}¶
fmt.Println(response)¶
```¶

```java Java¶
AnthropicClient client = AnthropicOkHttpClient.fromEnv();¶

MessageCreateParams params = MessageCreateParams.builder()¶
.model(Model.CLAUDE_OPUS_5)¶
.maxTokens(1024L)¶
.addUserMessage("Hello, Claude")¶
.build();¶

Message response = client.messages().create(params);¶
System.out.println(response);¶
```¶

```php PHP¶
$client = new Client();¶

$message = $client->messages->create(¶
maxTokens: 1024,¶
messages: [['role' => 'user', 'content' => 'Hello, Claude']],¶
model: 'claude-opus-5',¶
);¶
echo json_encode($message, JSON_PRETTY_PRINT), PHP_EOL;¶
```¶

```ruby Ruby¶
client = Anthropic::Client.new¶

message = client.messages.create(¶
model: "claude-opus-5",¶
max_tokens: 1024,¶
messages: [¶
{ role: "user", content: "Hello, Claude" }¶
]¶
)¶
puts message¶
```¶
</CodeGroup>¶

```json Output¶
{¶
"id": "msg_01XFDUDYJgAACzvnptvVoYEL",¶
"type": "message",¶
"role": "assistant",¶
"content": [¶
{¶
"type": "text",¶
"text": "Hello!"¶
}¶
],¶
"model": "claude-opus-5",¶
"stop_reason": "end_turn",¶
"stop_sequence": null,¶
"usage": {¶
"input_tokens": 12,¶
"output_tokens": 6¶
}¶
}¶
```¶

Refusal responses (`stop_reason: "refusal"`) also include a `stop_details` object identifying the policy category that triggered the refusal, on every model. See [Handling stop reasons](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#refusal-response) for the field reference and example handling code.¶

## Multiple conversational turns¶

The Messages API is stateless, which means that you always send the full conversational history to the API. You can use this pattern to build up a conversation over time. Earlier conversational turns don't necessarily need to actually originate from Claude. You can use synthetic `assistant` messages.¶

<CodeGroup>¶
```bash cURL¶
#!/bin/sh¶
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-opus-5",¶
"max_tokens": 1024,¶
"messages": [¶
{"role": "user", "content": "Hello, Claude"},¶
{"role": "assistant", "content": "Hello!"},¶
{"role": "user", "content": "Can you describe LLMs to me?"}¶

]¶
}'¶
```¶

```bash CLI¶
ant messages create \¶
--model claude-opus-5 \¶
--max-tokens 1024 \¶
--message '{role: user, content: "Hello, Claude"}' \¶
--message '{role: assistant, content: "Hello!"}' \¶
--message '{role: user, content: "Can you describe LLMs to me?"}'¶
```¶

```python Python¶
message = anthropic.Anthropic().messages.create(¶
model="claude-opus-5",¶
max_tokens=1024,¶
messages=[¶
{"role": "user", "content": "Hello, Claude"},¶
{"role": "assistant", "content": "Hello!"},¶
{"role": "user", "content": "Can you describe LLMs to me?"},¶
],¶
)¶
print(message)¶
```¶

```typescript TypeScript¶
const anthropic = new Anthropic();¶

const message = await anthropic.messages.create({¶
model: "claude-opus-5",¶
max_tokens: 1024,¶
messages: [¶
{ role: "user", content: "Hello, Claude" },¶
{ role: "assistant", content: "Hello!" },¶
{ role: "user", content: "Can you describe LLMs to me?" }¶
]¶
});¶
console.log(message);¶
```¶

```csharp C#¶
AnthropicClient client = new();¶

var parameters = new MessageCreateParams¶
{¶
Model = Model.ClaudeOpus5,¶
MaxTokens = 1024,¶
Messages =¶
[¶
new() { Role = Role.User, Content = "Hello, Claude" },¶
new() { Role = Role.Assistant, Content = "Hello!" },¶
new() { Role = Role.User, Content = "Can you describe LLMs to me?" }¶
]¶
};¶

var message = await client.Messages.Create(parameters);¶
Console.WriteLine(message);¶
```¶

```go Go¶
client := anthropic.NewClient()¶

response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{¶
Model: anthropic.ModelClaudeOpus5,¶
MaxTokens: 1024,¶
Messages: []anthropic.MessageParam{¶
anthropic.NewUserMessage(anthropic.NewTextBlock("Hello, Claude")),¶
anthropic.NewAssistantMessage(anthropic.NewTextBlock("Hello!")),¶
anthropic.NewUserMessage(anthropic.NewTextBlock("Can you describe LLMs to me?")),¶
},¶
})¶
if err != nil {¶
log.Fatal(err)¶
}¶
fmt.Println(response)¶
```¶

```java Java¶
AnthropicClient client = AnthropicOkHttpClient.fromEnv();¶

MessageCreateParams params = MessageCreateParams.builder()¶
.model(Model.CLAUDE_OPUS_5)¶
.maxTokens(1024L)¶
.addUserMessage("Hello, Claude")¶
.addAssistantMessage("Hello!")¶
.addUserMessage("Can you describe LLMs to me?")¶
.build();¶

Message response = client.messages().create(params);¶
System.out.println(response);¶
```¶

```php PHP¶
$client = new Client();¶

$message = $client->messages->create(¶
maxTokens: 1024,¶
messages: [¶
['role' => 'user', 'content' => 'Hello, Claude'],¶
['role' => 'assistant', 'content' => 'Hello!'],¶
['role' => 'user', 'content' => 'Can you describe LLMs to me?'],¶
],¶
model: 'claude-opus-5',¶
);¶

echo json_encode($message, JSON_PRETTY_PRINT), PHP_EOL;¶
```¶

```ruby Ruby¶
client = Anthropic::Client.new¶

message = client.messages.create(¶
model: "claude-opus-5",¶
max_tokens: 1024,¶
messages: [¶
{ role: "user", content: "Hello, Claude" },¶
{ role: "assistant", content: "Hello!" },¶
{ role: "user", content: "Can you describe LLMs to me?" }¶
]¶
)¶
puts message¶
```¶
</CodeGroup>¶

```json Output¶
{¶
"id": "msg_018gCsTGsXkYJVqYPxTgDHBU",¶
"type": "message",¶
"role": "assistant",¶
"content": [¶
{¶
"type": "text",¶
"text": "Sure, I'd be happy to provide..."¶
}¶
],¶
"model": "claude-opus-5",¶
"stop_reason": "end_turn",¶
"stop_sequence": null,¶
"usage": {¶
"input_tokens": 30,¶
"output_tokens": 309¶
}¶
}¶
```¶

### System role in messages¶

On Claude Fable 5, [Claude Mythos 5](https://anthropic.com/glasswing), Claude Opus 4.8, and Claude Opus 5, you can include messages with `"role": "system"` after a user turn (subject to [placement rules](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#limitations)) to add a new system instruction partway through a conversation. A `system` message cannot be the first entry in `messages`; use the top-level `system` field for instructions that apply from the start.¶

A mid-conversation system message has the same authority as the top-level `system` field, but because it is appended to the end of the message history, it does not invalidate any cached prefix that came before it. Use the top-level `system` field for instructions that should apply from the very first turn, and a mid-conversation system message for instructions that only become relevant later.¶

See [Mid-conversation system messages](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages) for the complete guide, including how to combine it with [prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching).¶

## Prefilling Claude's response¶

You can pre-fill part of Claude's response in the last position of the input messages list. Use this technique to shape Claude's response. The following example uses `"max_tokens": 1` to get a single multiple choice answer from Claude.¶

<Warning>¶
Prefilling is not supported on Claude 4.6 and later models and [Claude Mythos Preview](https://anthropic.com/glasswing). Requests using prefill with these models return a 400 error. Use [structured outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs) on models that support it, or system prompt instructions, instead. See the [migration guide](https://platform.claude.com/docs/en/about-claude/models/migration-guide) for migration patterns.¶
</Warning>¶

<CodeGroup>¶
```bash cURL¶
#!/bin/sh¶
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": 1,¶
"messages": [¶
{"role": "user", "content": "What is latin for Ant? (A) Apoidea, (B) Rhopalocera, (C) Formicidae"},¶
{"role": "assistant", "content": "The answer is ("}¶
]¶
}'¶
```¶

```bash CLI¶
ant messages create <<'YAML'¶
model: claude-sonnet-4-5¶
max_tokens: 1¶
messages:¶
- role: user¶
content: "What is latin for Ant? (A) Apoidea, (B) Rhopalocera, (C) Formicidae"¶
- role: assistant¶
content: "The answer is ("¶
YAML¶
```¶

```python Python¶
message = anthropic.Anthropic().messages.create(¶
model="claude-sonnet-4-5",¶
max_tokens=1,¶
messages=[¶
{¶
"role": "user",¶
"content": "What is latin for Ant? (A) Apoidea, (B) Rhopalocera, (C) Formicidae",¶
},¶
{"role": "assistant", "content": "The answer is ("},¶
],¶
)¶
print(message)¶
```¶

```typescript TypeScript¶
const anthropic = new Anthropic();¶

const message = await anthropic.messages.create({¶
model: "claude-sonnet-4-5",¶
max_tokens: 1,¶
messages: [¶
{¶
role: "user",¶
content: "What is latin for Ant? (A) Apoidea, (B) Rhopalocera, (C) Formicidae"¶
},¶
{ role: "assistant", content: "The answer is (" }¶
]¶
});¶
console.log(message);¶
```¶

```csharp C#¶
AnthropicClient client = new();¶

var parameters = new MessageCreateParams¶
{¶
Model = Model.ClaudeSonnet4_5,¶
MaxTokens = 1,¶
Messages = [¶
new() { Role = Role.User, Content = "What is latin for Ant? (A) Apoidea, (B) Rhopalocera, (C) Formicidae" },¶
new() { Role = Role.Assistant, Content = "The answer is (" }¶
]¶
};¶

var message = await client.Messages.Create(parameters);¶
Console.WriteLine(message);¶
```¶

```go Go¶
client := anthropic.NewClient()¶

response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{¶
Model: anthropic.ModelClaudeSonnet4_5,¶
MaxTokens: 1,¶
Messages: []anthropic.MessageParam{¶
anthropic.NewUserMessage(anthropic.NewTextBlock("What is latin for Ant? (A) Apoidea, (B) Rhopalocera, (C) Formicidae")),¶
anthropic.NewAssistantMessage(anthropic.NewTextBlock("The answer is (")),¶
},¶
})¶
if err != nil {¶
log.Fatal(err)¶
}¶
fmt.Println(response)¶
```¶

```java Java¶
AnthropicClient client = AnthropicOkHttpClient.fromEnv();¶

MessageCreateParams params = MessageCreateParams.builder()¶
.model(Model.CLAUDE_SONNET_4_5)¶
.maxTokens(1L)¶
.addUserMessage("What is latin for Ant? (A) Apoidea, (B) Rhopalocera, (C) Formicidae")¶
.addAssistantMessage("The answer is (")¶
.build();¶

Message response = client.messages().create(params);¶
System.out.println(response);¶
```¶

```php PHP¶
$client = new Client();¶

$message = $client->messages->create(¶
maxTokens: 1,¶
messages: [¶
['role' => 'user', 'content' => 'What is latin for Ant? (A) Apoidea, (B) Rhopalocera, (C) Formicidae'],¶
['role' => 'assistant', 'content' => 'The answer is ('],¶
],¶
model: 'claude-sonnet-4-5',¶
);¶
echo $message->content[0]->text;¶
```¶

```ruby Ruby¶
client = Anthropic::Client.new¶

message = client.messages.create(¶
model: "claude-sonnet-4-5",¶
max_tokens: 1,¶
messages: [¶
{¶
role: "user",¶
content: "What is latin for Ant? (A) Apoidea, (B) Rhopalocera, (C) Formicidae"¶
},¶
{ role: "assistant", content: "The answer is (" }¶
]¶
)¶
puts message¶
```¶
</CodeGroup>¶

```json Output¶
{¶
"id": "msg_01Q8Faay6S7QPTvEUUQARt7h",¶
"type": "message",¶
"role": "assistant",¶
"content": [¶
{¶
"type": "text",¶
"text": "C"¶
}¶
],¶
"model": "claude-sonnet-4-5",¶
"stop_reason": "max_tokens",¶
"stop_sequence": null,¶
"usage": {¶
"input_tokens": 42,¶
"output_tokens": 1¶
}¶
}¶
```¶

## Vision¶

Claude can read both text and images in requests. You can supply images using the `base64`, `url`, or `file` source types. The `file` source type references an image uploaded through the [Files API](https://platform.claude.com/docs/en/build-with-claude/files). Supported media types are `image/jpeg`, `image/png`, `image/gif`, and `image/webp`. See the [vision guide](https://platform.claude.com/docs/en/build-with-claude/vision) for more details.¶

<CodeGroup>¶
```bash cURL¶
#!/bin/sh¶

# Option 1: Base64-encoded image¶
IMAGE_URL="https://platform.claude.com/docs/images/vision-example.jpg"¶
IMAGE_MEDIA_TYPE="image/jpeg"¶
IMAGE_BASE64=$(curl "$IMAGE_URL" | base64 | tr -d '\n')¶

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 @- <<EOF¶
{¶
"model": "claude-opus-5",¶
"max_tokens": 1024,¶
"messages": [¶
{"role": "user", "content": [¶
{"type": "image", "source": {¶
"type": "base64",¶
"media_type": "$IMAGE_MEDIA_TYPE",¶
"data": "$IMAGE_BASE64"¶
}},¶
{"type": "text", "text": "What is in the above image?"}¶
]}¶
]¶
}¶
EOF¶

# Option 2: URL-referenced image¶
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-opus-5",¶
"max_tokens": 1024,¶
"messages": [¶
{"role": "user", "content": [¶
{"type": "image", "source": {¶
"type": "url",¶
"url": "https://platform.claude.com/docs/images/vision-example.jpg"¶
}},¶
{"type": "text", "text": "What is in the above image?"}¶
]}¶
]¶
}'¶
```¶

```bash CLI¶
IMAGE_URL="https://platform.claude.com/docs/images/vision-example.jpg"¶

# Option 1: Base64-encoded image (CLI auto-encodes binary @file refs)¶
curl -s "$IMAGE_URL" -o ./vision-example.jpg¶

ant messages create <<'YAML'¶
model: claude-opus-5¶
max_tokens: 1024¶
messages:¶
- role: user¶
content:¶
- type: image¶
source:¶
type: base64¶
media_type: image/jpeg¶
data: "@./vision-example.jpg"¶
- type: text¶
text: What is in the above image?¶
YAML¶

# Option 2: URL-referenced image¶
ant messages create <<YAML¶
model: claude-opus-5¶
max_tokens: 1024¶
messages:¶
- role: user¶
content:¶
- type: image¶
source:¶
type: url¶
url: $IMAGE_URL¶
- type: text¶
text: What is in the above image?¶
YAML¶
```¶

```python Python¶
import base64¶
import httpx2¶

# Option 1: Base64-encoded image¶
image_url = "https://platform.claude.com/docs/images/vision-example.jpg"¶
image_media_type = "image/jpeg"¶
image_data = base64.standard_b64encode(httpx2.get(image_url).content).decode("utf-8")¶

message = anthropic.Anthropic().messages.create(¶
model="claude-opus-5",¶
max_tokens=1024,¶
messages=[¶
{¶
"role": "user",¶
"content": [¶
{¶
"type": "image",¶
"source": {¶
"type": "base64",¶
"media_type": image_media_type,¶
"data": image_data,¶
},¶
},¶
{"type": "text", "text": "What is in the above image?"},¶
],¶
}¶
],¶
)¶
print(message)¶

# Option 2: URL-referenced image¶
message_from_url = anthropic.Anthropic().messages.create(¶
model="claude-opus-5",¶
max_tokens=1024,¶
messages=[¶
{¶
"role": "user",¶
"content": [¶
{¶
"type": "image",¶
"source": {¶
"type": "url",¶
"url": "https://platform.claude.com/docs/images/vision-example.jpg",¶
},¶
},¶
{"type": "text", "text": "What is in the above image?"},¶
],¶
}¶
],¶
)¶
print(message_from_url)¶
```¶

```typescript TypeScript¶
const anthropic = new Anthropic();¶

// Option 1: Base64-encoded image¶
const imageUrl = "https://platform.claude.com/docs/images/vision-example.jpg";¶
const imageMediaType = "image/jpeg";¶
const imageArrayBuffer = await (await fetch(imageUrl)).arrayBuffer();¶
const imageData = Buffer.from(imageArrayBuffer).toString("base64");¶

const message = await anthropic.messages.create({¶
model: "claude-opus-5",¶
max_tokens: 1024,¶
messages: [¶
{¶
role: "user",¶
content: [¶
{¶
type: "image",¶
source: {¶
type: "base64",¶
media_type: imageMediaType,¶
data: imageData¶
}¶
},¶
{¶
type: "text",¶
text: "What is in the above image?"¶
}¶
]¶
}¶
]¶
});¶
console.log(message);¶

// Option 2: URL-referenced image¶
const messageFromUrl = await anthropic.messages.create({¶
model: "claude-opus-5",¶
max_tokens: 1024,¶
messages: [¶
{¶
role: "user",¶
content: [¶
{¶
type: "image",¶
source: {¶
type: "url",¶
url: "https://platform.claude.com/docs/images/vision-example.jpg"¶
}¶
},¶
{¶
type: "text",¶
text: "What is in the above image?"¶
}¶
]¶
}¶
]¶
});¶
console.log(messageFromUrl);¶
```¶

```csharp C#¶
using System.Collections.Generic;¶
using System.Net.Http;¶
using Anthropic;¶
using Anthropic.Models.Messages;¶

AnthropicClient client = new();¶

// Option 1: Base64-encoded image¶
string imageUrl = "https://platform.claude.com/docs/images/vision-example.jpg";¶

using HttpClient httpClient = new();¶
byte[] imageBytes = await httpClient.GetByteArrayAsync(imageUrl);¶
string imageData = Convert.ToBase64String(imageBytes);¶

var parameters = new MessageCreateParams¶
{¶
Model = Model.ClaudeOpus5,¶
MaxTokens = 1024,¶
Messages =¶
[¶
new()¶
{¶
Role = Role.User,¶
Content = new MessageParamContent(new List<ContentBlockParam>¶
{¶
new ContentBlockParam(new ImageBlockParam(¶
new ImageBlockParamSource(new Base64ImageSource()¶
{¶
Data = imageData,¶
MediaType = MediaType.ImageJpeg,¶
})¶
)),¶
new ContentBlockParam(new TextBlockParam("What is in the above image?")),¶
}),¶
}¶
]¶
};¶

var message = await client.Messages.Create(parameters);¶
Console.WriteLine(message);¶

// Option 2: URL-referenced image¶
var parametersFromUrl = new MessageCreateParams¶
{¶
Model = Model.ClaudeOpus5,¶
MaxTokens = 1024,¶
Messages =¶
[¶
new()¶
{¶
Role = Role.User,¶
Content = new MessageParamContent(new List<ContentBlockParam>¶
{¶
new ContentBlockParam(new ImageBlockParam(¶
new ImageBlockParamSource(new UrlImageSource()¶
{¶
Url = "https://platform.claude.com/docs/images/vision-example.jpg",¶
})¶
)),¶
new ContentBlockParam(new TextBlockParam("What is in the above image?")),¶
}),¶
}¶
]¶
};¶

var messageFromUrl = await client.Messages.Create(parametersFromUrl);¶
Console.WriteLine(messageFromUrl);¶
```¶

```go Go¶
client := anthropic.NewClient()¶

// Option 1: Base64-encoded image¶
imageURL := "https://platform.claude.com/docs/images/vision-example.jpg"¶

req, err := http.NewRequest("GET", imageURL, nil)¶
if err != nil {¶
log.Fatal(err)¶
}¶
req.Header.Set("User-Agent", "AnthropicDocsBot/1.0")¶

resp, err := http.DefaultClient.Do(req)¶
if err != nil {¶
log.Fatal(err)¶
}¶
defer resp.Body.Close()¶

imageBytes, err := io.ReadAll(resp.Body)¶
if err != nil {¶
log.Fatal(err)¶
}¶
imageData := base64.StdEncoding.EncodeToString(imageBytes)¶

message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{¶
Model: anthropic.ModelClaudeOpus5,¶
MaxTokens: 1024,¶
Messages: []anthropic.MessageParam{¶
anthropic.NewUserMessage(¶
anthropic.NewImageBlockBase64("image/jpeg", imageData),¶
anthropic.NewTextBlock("What is in the above image?"),¶
),¶
},¶
})¶
if err != nil {¶
log.Fatal(err)¶
}¶
fmt.Println(message)¶

// Option 2: URL-referenced image¶
messageFromURL, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{¶
Model: anthropic.ModelClaudeOpus5,¶
MaxTokens: 1024,¶
Messages: []anthropic.MessageParam{¶
anthropic.NewUserMessage(¶
anthropic.NewImageBlock(anthropic.URLImageSourceParam{¶
URL: "https://platform.claude.com/docs/images/vision-example.jpg",¶
}),¶
anthropic.NewTextBlock("What is in the above image?"),¶
),¶
},¶
})¶
if err != nil {¶
log.Fatal(err)¶
}¶
fmt.Println(messageFromURL)¶
```¶

```java Java¶
AnthropicClient client = AnthropicOkHttpClient.fromEnv();¶

// Option 1: Base64-encoded image¶
String imageUrl = "https://platform.claude.com/docs/images/vision-example.jpg";¶

HttpClient httpClient = HttpClient.newHttpClient();¶
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(imageUrl)).build();¶
HttpResponse<byte[]> response = httpClient.send(request, HttpResponse.BodyHandlers.ofByteArray());¶
String imageData = Base64.getEncoder().encodeToString(response.body());¶

List<ContentBlockParam> base64Content = List.of(¶
ContentBlockParam.ofImage(¶
ImageBlockParam.builder()¶
.source(Base64ImageSource.builder()¶
.data(imageData)¶
.mediaType(Base64ImageSource.MediaType.IMAGE_JPEG)¶
.build())¶
.build()),¶
ContentBlockParam.ofText(¶
TextBlockParam.builder()¶
.text("What is in the above image?")¶
.build())¶
);¶

Message message = client.messages().create(¶
MessageCreateParams.builder()¶
.model(Model.CLAUDE_OPUS_5)¶
.maxTokens(1024L)¶
.addUserMessageOfBlockParams(base64Content)¶
.build());¶
System.out.println(message);¶

// Option 2: URL-referenced image¶
List<ContentBlockParam> urlContent = List.of(¶
ContentBlockParam.ofImage(¶
ImageBlockParam.builder()¶
.source(UrlImageSource.builder()¶
.url("https://platform.claude.com/docs/images/vision-example.jpg")¶
.build())¶
.build()),¶
ContentBlockParam.ofText(¶
TextBlockParam.builder()¶
.text("What is in the above image?")¶
.build())¶
);¶

Message messageFromUrl = client.messages().create(¶
MessageCreateParams.builder()¶
.model(Model.CLAUDE_OPUS_5)¶
.maxTokens(1024L)¶
.addUserMessageOfBlockParams(urlContent)¶
.build());¶
System.out.println(messageFromUrl);¶
```¶

```php PHP¶
$client = new Client();¶

// Option 1: Base64-encoded image¶
$image_url = 'https://platform.claude.com/docs/images/vision-example.jpg';¶
$image_media_type = "image/jpeg";¶
$image_data = base64_encode(file_get_contents($image_url));¶

$message = $client->messages->create(¶
maxTokens: 1024,¶
messages: [¶
[¶
'role' => 'user',¶
'content' => [¶
[¶
'type' => 'image',¶
'source' => [¶
'type' => 'base64',¶
'media_type' => $image_media_type,¶
'data' => $image_data,¶
],¶
],¶
[¶
'type' => 'text',¶
'text' => 'What is in the above image?',¶
],¶
],¶
],¶
],¶
model: 'claude-opus-5',¶
);¶
echo $message;¶

// Option 2: URL-referenced image¶
$message_from_url = $client->messages->create(¶
maxTokens: 1024,¶
messages: [¶
[¶
'role' => 'user',¶
'content' => [¶
[¶
'type' => 'image',¶
'source' => [¶
'type' => 'url',¶
'url' => 'https://platform.claude.com/docs/images/vision-example.jpg',¶
],¶
],¶
[¶
'type' => 'text',¶
'text' => 'What is in the above image?',¶
],¶
],¶
],¶
],¶
model: 'claude-opus-5',¶
);¶
echo $message_from_url;¶
```¶

```ruby Ruby¶
require "base64"¶
require "net/http"¶

client = Anthropic::Client.new¶

# Option 1: Base64-encoded image¶
image_url = "https://platform.claude.com/docs/images/vision-example.jpg"¶
image_media_type = "image/jpeg"¶
image_data = Base64.strict_encode64(Net::HTTP.get(URI(image_url)))¶

message = client.messages.create(¶
model: "claude-opus-5",¶
max_tokens: 1024,¶
messages: [¶
{¶
role: "user",¶
content: [¶
{¶
type: "image",¶
source: {¶
type: "base64",¶
media_type: image_media_type,¶
data: image_data¶
}¶
},¶
{¶
type: "text",¶
text: "What is in the above image?"¶
}¶
]¶
}¶
]¶
)¶
puts message¶

# Option 2: URL-referenced image¶
message_from_url = client.messages.create(¶
model: "claude-opus-5",¶
max_tokens: 1024,¶
messages: [¶
{¶
role: "user",¶
content: [¶
{¶
type: "image",¶
source: {¶
type: "url",¶
url: "https://platform.claude.com/docs/images/vision-example.jpg"¶
}¶
},¶
{¶
type: "text",¶
text: "What is in the above image?"¶
}¶
]¶
}¶
]¶
)¶
puts message_from_url¶
```¶
</CodeGroup>¶

```json Output¶
{¶
"id": "msg_011CdKmWtV3oFx1C5yUbf5CY",¶
"type": "message",¶
"role": "assistant",¶
"content": [¶
{¶
"type": "text",¶
"text": "This image is a beautiful minimalist/flat-design illustration of a sunset landscape. Here's what it contains:\n\n**Sky & Sun:**\n- A warm gradient sky transitioning from golden-yellow at the top to deep orange toward the horizon\n- A large pale yellow sun positioned in the upper-right area\n\n**Birds:**\n- Three small silhouetted birds flying in the upper-left portion of the sky, depicted as simple \"M\" or \"v\" shapes\n\n**Mountains:**\n- Multiple layered mountain peaks in purple and maroon tones\n- The mountains overlap to create depth, with varying shades of dusty purple and deep burgundy\n\n**Water:**\n- A dark purple body of water at the bottom of the image\n- A reflection of the sun shown as horizontal cream/peach colored lines in the center-bottom area\n\nThe overall style is clean, geometric, and uses a warm sunset color palette (oranges, yellows, purples, and maroons), giving it a peaceful, serene aesthetic typical of modern vector/flat design artwork."¶
}¶
],¶
"model": "claude-opus-5",¶
"stop_reason": "end_turn",¶
"stop_sequence": null,¶
"usage": {¶
"input_tokens": 1030,¶
"output_tokens": 350¶
}¶
}¶
```¶

## Next steps¶

<CardGroup cols={2}>¶
<Card title="Stop reasons and fallback" icon="list" href="https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons">¶
Handle each `stop_reason` value and decide what to do when a response ends.¶
</Card>¶

<Card title="Tool use with Claude" icon="wrench" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview">¶
Give Claude tools to call external services and APIs from within the Messages API.¶
</Card>¶

<Card title="Computer use tool" icon="computer" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool">¶
Control desktop computer environments with the Messages API.¶
</Card>¶

<Card title="Browser use tool" icon="browser" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/browser-use-tool">¶
Let Claude navigate, read, and interact with webpages in a browser you run.¶
</Card>¶

<Card title="Structured outputs" icon="code-brackets" href="https://platform.claude.com/docs/en/build-with-claude/structured-outputs">¶
Get guaranteed, schema-validated JSON output from Claude.¶
</Card>¶

<Card title="Task budgets" icon="gauge" href="https://platform.claude.com/docs/en/build-with-claude/task-budgets">¶
Set an advisory token budget across a full agentic loop with `output_config.task_budget`.¶
</Card>¶
</CardGroup>¶

Unified Diff

--- a/build-with-claude/working-with-messages.md
+++ b/build-with-claude/working-with-messages.md
@@ -14,7 +14,7 @@
 This guide covers common patterns for working with the Messages API, including basic requests, multi-turn conversations, prefill techniques, and vision capabilities. For complete API specifications, see the [Messages API reference](https://platform.claude.com/docs/en/api/messages/create). For the managed agent harness instead, see the [Claude Managed Agents overview](https://platform.claude.com/docs/en/managed-agents/overview).
 
 <Note>
-  For how zero data retention (ZDR) applies to this feature, see [API and data retention](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention).
+  To learn how zero data retention (ZDR) applies to this feature, see [API and data retention](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention).
 </Note>
 
 ## Basic request and response