Source Intelligence
Sweep 28 Aug 2026 · 00:00Z Build v2.1.250 478 read Stable v2.1.236 Latest v2.1.250 Next v2.1.251 Feeds RSS JSON llms.txt
Reading a new release v2.1.251 Analysing changes · 2/5 Deeper second pass · 0/5 agents 427 findings $12.75 so far

DisclaimerUnofficial, and not affiliated with Anthropic. Nearly all of this is read straight out of what ships: npm bundles, captured prompts, published docs. Anthropic's own notes go in verbatim, marked as theirs. The rest is my reading, and every entry carries the strings behind it. If one looks wrong, vote it down and say why.

Page history

vision

build-with-claude/vision

5 recorded changes 1377 lines First seen Last changed Upstream

History

build-with-claude/vision Changed · +8 / -9 lines

from line 792
   ```
 
   ```php PHP
-  // The PHP SDK exposes the Files API under the beta namespace; field names can differ from other SDKs.
-  // The PHP SDK supports file_id document and image sources only through $client->beta->messages with the files beta.
+  use Anthropic\Core\FileParam;
+
   $client = new Client();
 
   // Upload the image file
-  $fileUpload = $client->beta->files->upload(
-      FileParam::fromResource(fopen('vision-example.jpg', 'rb'), contentType: 'image/jpeg'),
+  $fileUpload = $client->files->upload(
+      file: FileParam::fromResource(fopen('vision-example.jpg', 'rb'), contentType: 'image/jpeg'),
   );
 
   // Use the uploaded file in a message
-  $message = $client->beta->messages->create(
+  $message = $client->messages->create(
       maxTokens: 1024,
       messages: [
           [
from line 810
               'content' => [
                   [
                       'type' => 'image',
-                      'source' => ['type' => 'file', 'file_id' => $fileUpload->id],
+                      'source' => ['type' => 'file', 'fileID' => $fileUpload->id],
                   ],
                   ['type' => 'text', 'text' => 'Describe this image.'],
               ],
from line 817
           ],
       ],
       model: 'claude-opus-5',
-      betas: ['files-api-2025-04-14'],
   );
 
   echo json_encode($message, JSON_PRETTY_PRINT), PHP_EOL;
from line 1257
 
 Claude views images in patches instead of pixels. Each patch is a 28×28-pixel block of the image, referred to as a visual token. An image, therefore, costs `⌈width / 28⌉ × ⌈height / 28⌉` visual tokens.
 
-Each model has a maximum native image resolution, expressed as a long-edge limit and a visual-token limit. Images larger than either limit are downscaled before processing; see [How Claude resizes and pads images](https://platform.claude.com/docs/en/build-with-claude/vision-coordinates#how-claude-resizes-and-pads-images) for the exact rule. The exception is screenshots and zoom images that you return to the [computer use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#handle-coordinate-scaling-for-higher-resolutions) and [browser use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/browser-use-tool#targets-and-coordinates) toolsets: the API rejects a `tool_result` image that exceeds the model's limits with a validation error instead of downscaling it, so resize those images in your application before returning them.
+Each model has a maximum native image resolution, expressed as a long-edge limit and a visual-token limit. Images larger than either limit are downscaled before processing; see [How Claude resizes and pads images](https://platform.claude.com/docs/en/build-with-claude/vision-coordinates#how-claude-resizes-and-pads-images) for the exact rule. The exception is screenshots and zoom images that you return to the [computer use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#handle-coordinate-scaling-for-higher-resolutions) and [browser use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/browser-use-tool#targets-and-coordinates) toolsets: the API rejects a `tool_result` image that exceeds the model's limits with a validation error instead of downscaling it, so resize those images in your application before returning them. To have any other oversized image rejected with an error instead of downscaled, set the image block's [`transformations` field](https://platform.claude.com/docs/en/build-with-claude/vision-coordinates#oversized-image-error).
 
 | Resolution tier | Models                      | Max long edge | Max visual tokens |
 | --------------- | --------------------------- | ------------- | ----------------- |
from line 1289
 
 * **Image clarity:** Ensure images are clear and not too blurry or pixelated.
 * **Text:** If the image contains important text, make sure it's legible and not too small. Avoid cropping out key visual context solely to enlarge the text.
-* **Resizing:** Take into account that your image might be resized if it is too large (see [Resolution and token cost](https://platform.claude.com/docs/en/build-with-claude/vision#evaluate-image-size)); this might, for example, make text less legible. Consider pre-resizing your images, cropping them, or both.
+* **Resizing:** Take into account that your image might be resized if it is too large (see [Resolution and token cost](https://platform.claude.com/docs/en/build-with-claude/vision#evaluate-image-size)); this might, for example, make text less legible. Consider pre-resizing your images, cropping them, or both. To have an oversized image rejected with an error instead of resized (important for [coordinate workflows](https://platform.claude.com/docs/en/build-with-claude/vision-coordinates)), mark the image block with [`"oversized_image": "error"`](https://platform.claude.com/docs/en/build-with-claude/vision-coordinates#oversized-image-error).
 * **Image compression:** Compressing images before sending them, using a lossy format such as JPEG or WebP (lossy mode), can reduce latency by reducing the size of requests. However, this can introduce artifacts that are detrimental to model performance, especially when multiple compression passes are applied. For example, heavy JPEG compression can make text difficult to read. Confirm your compression settings are appropriate for the task by inspecting the actual images sent to the API.
 
 ***

build-with-claude/vision Changed · +4 / -2 lines

from line 792
   ```
 
   ```php PHP
+  // The PHP SDK exposes the Files API under the beta namespace; field names can differ from other SDKs.
+  // The PHP SDK supports file_id document and image sources only through $client->beta->messages with the files beta.
   $client = new Client();
 
   // Upload the image file
from line 1236
 
 The maximum dimensions per image are 8000x8000 px.
 
-If a single API request contains more than 20 images, a stricter per-image dimension limit applies. On Amazon Bedrock and Google Cloud, document blocks such as PDFs also count toward this threshold. Images exceeding the stricter limit are rejected with an `invalid_request_error` whose message references "many-image requests" and states the current limit in pixels. To stay under the limit on all platforms, either resize each image so that neither dimension exceeds 2000 px, or keep the request to 20 or fewer image and document blocks.
+If a single API request contains more than 20 images, a stricter per-image dimension limit applies to every image in that request. All `image` blocks in the request count toward this threshold, including images from earlier conversation turns that you resend and images nested inside `tool_result` content (for example, screenshots returned to the computer use tool). On Amazon Bedrock and Google Cloud, document blocks such as PDFs also count toward this threshold. Images exceeding the stricter limit are rejected with an `invalid_request_error` whose message references "many-image requests" and states the current limit in pixels. To stay under the limit on all platforms, either resize each image so that neither dimension exceeds 2000 px, or keep the request to 20 or fewer image and document blocks.
 
 The maximum size per image is:
 
from line 1258
 
 Claude views images in patches instead of pixels. Each patch is a 28×28-pixel block of the image, referred to as a visual token. An image, therefore, costs `⌈width / 28⌉ × ⌈height / 28⌉` visual tokens.
 
-Each model has a maximum native image resolution, expressed as a long-edge limit and a visual-token limit. Images larger than either limit are downscaled before processing; see [How Claude resizes and pads images](https://platform.claude.com/docs/en/build-with-claude/vision-coordinates#how-claude-resizes-and-pads-images) for the exact rule.
+Each model has a maximum native image resolution, expressed as a long-edge limit and a visual-token limit. Images larger than either limit are downscaled before processing; see [How Claude resizes and pads images](https://platform.claude.com/docs/en/build-with-claude/vision-coordinates#how-claude-resizes-and-pads-images) for the exact rule. The exception is screenshots and zoom images that you return to the [computer use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#handle-coordinate-scaling-for-higher-resolutions) and [browser use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/browser-use-tool#targets-and-coordinates) toolsets: the API rejects a `tool_result` image that exceeds the model's limits with a validation error instead of downscaling it, so resize those images in your application before returning them.
 
 | Resolution tier | Models                      | Max long edge | Max visual tokens |
 | --------------- | --------------------------- | ------------- | ----------------- |

build-with-claude/vision Changed · +68 / -61 lines

from line 541
   FILE_ID=$(curl -sS -X POST https://api.anthropic.com/v1/files \
     -H "x-api-key: $ANTHROPIC_API_KEY" \
     -H "anthropic-version: 2023-06-01" \
-    -H "anthropic-beta: files-api-2025-04-14" \
     -F "[email protected]" | jq -r '.id')
 
   # Then use the returned file_id in your message
from line 547
   curl https://api.anthropic.com/v1/messages \
     -H "x-api-key: $ANTHROPIC_API_KEY" \
     -H "anthropic-version: 2023-06-01" \
-    -H "anthropic-beta: files-api-2025-04-14" \
     -H "content-type: application/json" \
     -d @- <<EOF
   {
from line 579
     https://platform.claude.com/docs/images/vision-example.jpg
 
   # First, upload your image to the Files API
-  FILE_ID=$(ant beta:files upload \
+  FILE_ID=$(ant files upload \
     --file ./vision-example.jpg \
     --transform id --raw-output)
 
   # Then use the returned file_id in your message
-  ant beta:messages create \
-    --beta files-api-2025-04-14 \
+  ant messages create \
     --transform content --format yaml <<YAML
   model: claude-opus-5
   max_tokens: 1024
from line 605
 
   # Upload the image file
   with open("vision-example.jpg", "rb") as f:
-      file_upload = client.beta.files.upload(file=("vision-example.jpg", f, "image/jpeg"))
+      file_upload = client.files.upload(file=("vision-example.jpg", f, "image/jpeg"))
 
   # Use the uploaded file in a message
-  message = client.beta.messages.create(
+  message = client.messages.create(
       model="claude-opus-5",
       max_tokens=1024,
-      betas=["files-api-2025-04-14"],
       messages=[
           {
               "role": "user",
from line 635
   const anthropic = new Anthropic();
 
   // Upload the image file
-  const fileUpload = await anthropic.beta.files.upload({
+  const fileUpload = await anthropic.files.upload({
     file: await toFile(fs.createReadStream("vision-example.jpg"), undefined, {
       type: "image/jpeg"
     })
from line 642
   });
 
   // Use the uploaded file in a message
-  const response = await anthropic.beta.messages.create({
+  const response = await anthropic.messages.create({
     model: "claude-opus-5",
     max_tokens: 1024,
-    betas: ["files-api-2025-04-14"],
     messages: [
       {
         role: "user",
from line 669
   ```
 
   ```csharp C#
+  using System.Collections.Generic;
   using Anthropic;
+  using Anthropic.Core;
+  using Anthropic.Models.Files;
+  using Anthropic.Models.Messages;
 
-  var client = new AnthropicClient();
+  AnthropicClient client = new();
 
   // Upload the image file
-  var fileUpload = await client.Beta.Files.Upload(
-      new FileUploadParams { File = File.OpenRead("vision-example.jpg") });
+  var fileUpload = await client.Files.Upload(new FileUploadParams
+  {
+      File = new BinaryContent
+      {
+          Stream = File.OpenRead("vision-example.jpg"),
+          FileName = "vision-example.jpg",
+          ContentType = new("image/jpeg"),
+      },
+  });
 
   // Use the uploaded file in a message
-  var response = await client.Beta.Messages.Create(
-      new MessageCreateParams
-      {
-          Model = "claude-opus-5",
-          MaxTokens = 1024,
-          Betas = new[] { "files-api-2025-04-14" },
-          Messages = new[]
+  var response = await client.Messages.Create(new MessageCreateParams
+  {
+      Model = Model.ClaudeOpus5,
+      MaxTokens = 1024,
+      Messages =
+      [
+          new()
           {
-              new BetaMessageParam
+              Role = Role.User,
+              Content = new MessageParamContent(new List<ContentBlockParam>
               {
-                  Role = "user",
-                  Content = new object[]
-                  {
-                      new
-                      {
-                          type = "image",
-                          source = new { type = "file", file_id = fileUpload.Id }
-                      },
-                      new { type = "text", text = "Describe this image." }
-                  }
-              }
+                  new ContentBlockParam(new ImageBlockParam(
+                      new ImageBlockParamSource(new FileImageSource(fileUpload.ID))
+                  )),
+                  new ContentBlockParam(new TextBlockParam("Describe this image.")),
+              }),
           }
-      });
+      ]
+  });
 
   Console.WriteLine(response);
   ```
from line 722
   }
   defer file.Close()
 
-  fileUpload, err := client.Beta.Files.Upload(context.Background(),
-  	anthropic.BetaFileUploadParams{
-  		File: file,
+  fileUpload, err := client.Files.Upload(context.Background(),
+  	anthropic.FileUploadParams{
+  		File: anthropic.File(file, "vision-example.jpg", "image/jpeg"),
   	})
   if err != nil {
   	log.Fatal(err)
from line 731
   }
 
   // Use the uploaded file in a message
-  message, err := client.Beta.Messages.New(context.Background(),
-  	anthropic.BetaMessageNewParams{
+  message, err := client.Messages.New(context.Background(),
+  	anthropic.MessageNewParams{
   		Model:     anthropic.ModelClaudeOpus5,
   		MaxTokens: 1024,
-  		Betas:     []anthropic.AnthropicBeta{anthropic.AnthropicBetaFilesAPI2025_04_14},
-  		Messages: []anthropic.BetaMessageParam{
-  			anthropic.NewBetaUserMessage(
-  				anthropic.NewBetaImageBlock(anthropic.BetaFileImageSourceParam{
+  		Messages: []anthropic.MessageParam{
+  			anthropic.NewUserMessage(
+  				anthropic.NewImageBlock(anthropic.FileImageSourceParam{
   					FileID: fileUpload.ID,
   				}),
-  				anthropic.NewBetaTextBlock("Describe this image."),
+  				anthropic.NewTextBlock("Describe this image."),
   			),
   		},
   	})
from line 752
   ```
 
   ```java Java
-  import com.anthropic.models.beta.files.FileMetadata;
-  import com.anthropic.models.beta.files.FileUploadParams;
+  import com.anthropic.core.MultipartField;
+  import com.anthropic.models.files.FileMetadata;
+  import com.anthropic.models.files.FileUploadParams;
   // ...
       AnthropicClient client = AnthropicOkHttpClient.fromEnv();
 
       // Upload the image file
-      FileMetadata file = client
-        .beta()
-        .files()
-        .upload(
-          FileUploadParams.builder()
-            .file(Files.newInputStream(Path.of("vision-example.jpg")))
-            .build()
-        );
+      FileMetadata file = client.files().upload(
+        FileUploadParams.builder()
+          .file(
+            MultipartField.<InputStream>builder()
+              .value(Files.newInputStream(Path.of("vision-example.jpg")))
+              .filename("vision-example.jpg")
+              .contentType("image/jpeg")
+              .build()
+          )
+          .build()
+      );
 
       // Use the uploaded file in a message
       ImageBlockParam imageParam = ImageBlockParam.builder().fileSource(file.id()).build();
from line 796
 
   // Upload the image file
   $fileUpload = $client->beta->files->upload(
-      file: fopen('vision-example.jpg', 'r'),
+      FileParam::fromResource(fopen('vision-example.jpg', 'rb'), contentType: 'image/jpeg'),
   );
 
   // Use the uploaded file in a message
from line 825
   client = Anthropic::Client.new
 
   # Upload the image file
-  file_upload = client.beta.files.upload(
-    file: File.open("vision-example.jpg", "rb")
+  file_upload = client.files.upload(
+    file: Anthropic::FilePart.new(
+      File.open("vision-example.jpg", "rb"),
+      content_type: "image/jpeg"
+    )
   )
 
   # Use the uploaded file in a message
-  message = client.beta.messages.create(
+  message = client.messages.create(
     model: "claude-opus-5",
     max_tokens: 1024,
-    betas: ["files-api-2025-04-14"],
     messages: [
       {
         role: "user",

build-with-claude/vision Changed · +1 / -1 lines

from line 13
 Use Claude's vision capabilities through:
 
 * [claude.ai](https://claude.ai/). Upload an image like you would a file, or drag and drop an image directly into the chat window.
-* The [Workbench](https://platform.claude.com/playground) in the Claude Console. Add images directly to any User message block.
+* [Playground](https://platform.claude.com/playground) in the Claude Console. Add images directly to any User message block.
 * API request. See the following examples.
 
 On the API, provide images to Claude as `image` content blocks using one of three source types:

build-with-claude/vision First recorded · 1369 lines, first recorded

## Send images to Claude ### Base64-encoded image example ### URL-based image example ### Files API image example ### Multiple images ## Image limits and costs ### Request limits ### Supported formats ### Resolution and token cost ### Image quality guidance ## Coordinates and bounding boxes ## Limitations ## FAQ ## Next steps

The first capture of this source. The page was already there, and this is what it said.

---
title: Vision
url: https://platform.claude.com/docs/en/build-with-claude/vision
description: Claude's vision capabilities allow it to understand and analyze images, opening up exciting possibilities for multimodal interaction.
---

This guide describes how to send images to Claude, the limits and costs that apply, and where to find guidance for [coordinate-based workflows](https://platform.claude.com/docs/en/build-with-claude/vision-coordinates).

***

## Send images to Claude

Use Claude's vision capabilities through:

* [claude.ai](https://claude.ai/). Upload an image like you would a file, or drag and drop an image directly into the chat window.
* The [Workbench](https://platform.claude.com/playground) in the Claude Console. Add images directly to any User message block.
* API request. See the following examples.

On the API, provide images to Claude as `image` content blocks using one of three source types:

1. A base64-encoded image embedded in the request body
2. A URL reference to an image hosted online
3. A `file_id` returned by the [Files API](https://platform.claude.com/docs/en/build-with-claude/files) (upload once, reference many times)

<Note>
  On Amazon Bedrock and Google Cloud, only base64-encoded sources are currently available.
</Note>

<Tip>
  Just as [placing long documents before your query](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices#long-context-prompting) improves results in text prompts, Claude works best when images come before text. Images placed after text or interpolated with text still perform well, but if your use case allows it, prefer an image-then-text structure.
</Tip>

### Base64-encoded image example

<CodeGroup>
  ```bash cURL
  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/jpeg",
              "data": "$BASE64_IMAGE_DATA"
            }
          },
          {
            "type": "text",
            "text": "Describe this image."
          }
        ]
      }
    ]
  }
  EOF
  ```

  ```bash CLI
  curl -sSo ./vision-example.jpg \
    https://platform.claude.com/docs/images/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: Describe this image.
  YAML
  ```

  ```python Python
  image1_data = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC"
  image1_media_type = "image/png"

  client = anthropic.Anthropic()
  message = client.messages.create(
      model="claude-opus-5",
      max_tokens=1024,
      messages=[
          {
              "role": "user",
              "content": [
                  {
                      "type": "image",
                      "source": {
                          "type": "base64",
                          "media_type": image1_media_type,
                          "data": image1_data,
                      },
                  },
                  {"type": "text", "text": "Describe this image."},
              ],
          }
      ],
  )
  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: [
          {
            type: "image",
            source: {
              type: "base64",
              media_type: "image/jpeg",
              data: imageData // Base64-encoded image data as string
            }
          },
          {
            type: "text",
            text: "Describe this image."
          }
        ]
      }
    ]
  });

  console.log(message);
  ```

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

  AnthropicClient client = new();

  string imageData = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC";

  var message = await client.Messages.Create(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.ImagePng,
                      })
                  )),
                  new ContentBlockParam(new TextBlockParam("Describe this image.")),
              }),
          }
      ]
  });

  Console.WriteLine(message);
  ```

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

  imageData := "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC"

  message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5,
  	MaxTokens: 1024,
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(
  			anthropic.NewImageBlockBase64("image/png", imageData),
  			anthropic.NewTextBlock("Describe this image."),
  		),
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Println(message)
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();
  String imageData =
    "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC";

  List<ContentBlockParam> contentBlockParams = List.of(
    ContentBlockParam.ofImage(
      ImageBlockParam.builder()
        .source(
          Base64ImageSource.builder()
            .mediaType(Base64ImageSource.MediaType.IMAGE_PNG)
            .data(imageData)
            .build()
        )
        .build()
    ),
    ContentBlockParam.ofText(TextBlockParam.builder().text("Describe this image.").build())
  );
  Message message = client
    .messages()
    .create(
      MessageCreateParams.builder()
        .model(Model.CLAUDE_OPUS_5)
        .maxTokens(1024)
        .addUserMessageOfBlockParams(contentBlockParams)
        .build()
    );

  IO.println(message);
  ```

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

  $imageData = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC";

  $message = $client->messages->create(
      maxTokens: 1024,
      messages: [
          [
              'role' => 'user',
              'content' => [
                  [
                      'type' => 'image',
                      'source' => [
                          'type' => 'base64',
                          'media_type' => 'image/png',
                          'data' => $imageData,
                      ],
                  ],
                  ['type' => 'text', 'text' => 'Describe this image.'],
              ],
          ],
      ],
      model: 'claude-opus-5',
  );

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

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

  image_data = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC"

  message = client.messages.create(
    model: "claude-opus-5",
    max_tokens: 1024,
    messages: [
      {
        role: "user",
        content: [
          {
            type: "image",
            source: {
              type: "base64",
              media_type: "image/png",
              data: image_data
            }
          },
          { type: "text", text: "Describe this image." }
        ]
      }
    ]
  )

  puts message
  ```
</CodeGroup>

### URL-based image example

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \

Cut at 300 lines.