← 返回
AI技术

Claude 现在能读 2576px 截图,同一张 PNG 的 token 可能贵 3 倍

✍️ zhirenhun 📅 2026/11/5 👁 16 阅读 ⏱ 23 分钟
Claude 现在能读 2576px 截图,同一张 PNG 的 token 可能贵 3 倍

今年 4 月,Simon Willison 把一张 3456×2234、3.7 MB 的 PNG 截图喂进了他的 Claude token 计数器。在 Claude Opus 4.6 上,这张图算出来是 1,578 个 token;换到 Opus 4.7,同一个文件变成了 4,744 个。一张图,token 数涨了 3.01 倍,而两个模型的输入价格都是每百万 token 5 美元。

同一个文件,不同模型。Opus 4.7 支持长边最大 2,576 像素的图片,约合 375 万像素;而更早的 Claude 模型会把超出 1,568 像素的图片一律缩小。Anthropic 的视觉文档现在规定,从 Claude 4.7 起所有模型都默认进入高分辨率档位,无需手动开启。如果你的应用会发送截图,那么你按旧模型估算的单图成本,可能只有同一张 PNG 在当前模型上实际花费的三分之一。

小图没有变化。同一篇文章里,一张 682×318 的图片在 4.7 上花费 314 个 token,在 4.6 上是 310 个。多出来的成本只存在于大图中,而决定成本的规则一行算术就能说清。

Claude 按 28 像素的图块计费

Claude 并不按像素计价。视觉文档写明,它会把图片切成 28×28 像素的小块,每块计一个视觉 token:ceil(width / 28) × ceil(height / 28)。一张 1000×1000 的图片就是 36 × 36 = 1,296 个 token。

不过这里有个上限。每个模型都有长边限制和视觉 token 预算,图片只要超出其中任何一项,就会被等比缩小,直到符合要求:

档位 模型 最大长边 最大视觉 token
高分辨率 Claude 4.7 及更高版本 2,576 px 4,784
标准 其他所有模型 1,568 px 1,568

真正卡住的是 token 预算。Anthropic 的坐标指南指出,几乎所有照片和截图最终尺寸都由 token 上限决定,而不是长边:一张 1920×1080 的截图在标准档模型上会变成 1456×819,而不是 1568×882。在高分辨率模型上,同一张截图完全不会被缩放,消耗 2,691 个 token,而不是 1,560 个。

用指南里的参考缩放函数,把 Simon 那张截图套进这些规则,算出来的数字正好对得上。标准档下,3456×2234 缩到 1372×887:49 × 32 = 1,568 个 patch,恰好等于预算。高分辨率档下缩到 2383×1540:86 × 55 = 4,730 个 patch。这个比例是 3.02 倍,而他实测是 3.01 倍。这是我算出来的,不是实测;他计数里多出的 10 到 14 个 token,很可能是请求其余部分的开销,token 计数器会把它算进去。


Claude 按方形图块计费,所以长边越长,账单上的图块就越多。

/750 这个捷径在哪里失准

更老的捷径 width × height / 750 至今仍被引用,比如 fast.io 的这篇文章就称它是 Anthropic 的既定经验法则。由于 28 × 28 = 784,两者在中等尺寸图片上只差几个百分点:1000×1000 的图片按捷径算是 1,333,按 patch 算是 1,296。它会在三个地方失准。

它忽略了上限。3456×2234 / 750 是 10,294 个 token,这个数字两个档位都不会真的计费,因为图片会先被缩小。对高分辨率模型来说,这个估算高了约 2 倍;对标准档模型来说,高了 6 倍以上。

它忽略了取整。patch 在每个轴上都向上取整。1120×700 正好是 40 × 25 = 1,000 个 token。每边各加一个像素,变成 1121×701,就成了 41 × 26 = 1,066。而捷径只变动了约 2。

它并不知道你用的是哪个模型档位。同一张图、同一套公式,只因请求里的模型 ID 不同,结果最多能差 3 倍。

完全无关的是文件大小。公式里没有任何一处看字节数,坐标指南也指出,token 计数端点根据图片尺寸估算成本,并不会完整处理图片。同样尺寸下,3.7 MB 的 PNG 和 300 KB 的 JPEG 消耗的 token 一样。压缩只影响延迟和请求体积,而视觉文档提醒,有损 JPEG 或 WebP 可能引入伪影,让文字难以辨认——这恰恰是截图最不想要的效果。文件大小仍受限制约束:Claude API 上每张图 base64 编码后上限 10 MB,Amazon Bedrock 上为 5 MB。

用 TypeScript 自己算

token 计数端点免费,按使用档位限流(Start 档每分钟 5,000 次请求),支持所有在用模型。它只统计以 base64 发送的图片,不认 URL 或文件 ID。这足够你打印出自己的表格。

下面的脚本用到 Anthropic TypeScript SDK 和 sharp。它把一张截图缩放到几个不同的长边尺寸,分别在两个模型上计数,再减去纯文本基线,只留下图片部分,最后打印每千张图的 token 数和美元成本。这个脚本我自己没跑过,所以请以它打印出的数字为准,而不是本文里的数字。

// count-image.mts
// npm i @anthropic-ai/sdk sharp
// ANTHROPIC_API_KEY=... npx tsx count-image.mts shot.png
import Anthropic from "@anthropic-ai/sdk";
import sharp from "sharp";
import { readFile } from "node:fs/promises";

const client = new Anthropic();

const MODELS = [
  { id: "claude-opus-4-6", usdPerMTok: 5 },
  { id: "claude-opus-4-7", usdPerMTok: 5 },
];
// long-edge targets in px; 0 = send the original size
const EDGES = [0, 2576, 1568, 1092, 768];
const PROMPT = "What is on this screen?";

const patches = (w: number, h: number) =>
  Math.ceil(w / 28) * Math.ceil(h / 28);

async function count(model: string, png?: Buffer) {
  const text = { type: "text" as const, text: PROMPT };
  const content = png
    ? [
        {
          type: "image" as const,
          source: {
            type: "base64" as const,
            media_type: "image/png" as const,
            data: png.toString("base64"),
          },
        },
        text,
      ]
    : [text];
  const res = await client.messages.countTokens({
    model,
    messages: [{ role: "user", content }],
  });
  return res.input_tokens;
}

用 sharp 按各目标长边缩放,不做放大处理:

async function atEdge(src: Buffer, edge: number) {
  const img = sharp(src);
  if (edge > 0) {
    img.resize({
      width: edge,
      height: edge,
      fit: "inside",
      withoutEnlargement: true,
    });
  }
  return img.png().toBuffer();
}

主循环统计两个模型上每种尺寸的数量,并打印表格:

const src = await readFile(process.argv[2]);
const rows: Record<string, unknown>[] = [];

for (const m of MODELS) {
  const baseline = await count(m.id);
  for (const edge of EDGES) {
    const png = await atEdge(src, edge);
    const meta = await sharp(png).metadata();
    const w = meta.width ?? 0;
    const h = meta.height ?? 0;
    const tokens = (await count(m.id, png)) - baseline;
    rows.push({
      model: m.id,
      sent: `${w}x${h}`,
      kb: Math.round(png.length / 1024),
      predicted: patches(w, h),
      counted: tokens,
      usdPer1k: ((tokens * m.usdPerMTok) / 1000).toFixed(2),
    });
  }
}

console.table(rows);

kb 列在不同行之间会大幅波动,而 counted 列并不会跟着它走,因为字节数不在计算公式里。而 predicted 是你发送的像素对应的 patch 数量:当 counted 落在它上面或附近时,说明 Claude 看到的就是你发送时的尺寸。当 counted 明显低于它时,说明服务器把图片压缩到了该档位的预算上限,你为那些本可以自己裁掉的像素付了钱。对于 Opus 4.7 上一张 3456×2234 的截图,原图和 2,576 行都应该落在 4,730 附近,也就是服务器把这张图压缩到的尺寸。一张 2576×1665 的图片仍然是 92 × 60 = 5,520 个 patch,超过了 4,784 的预算。

发送前先选好尺寸

下面是一张截图在每千次请求下的图像 token 成本,根据文档中的 token 表和每个模型的输入价格计算得出。这里没有计入你的提示词文本和输出 token。

模型 档位 输入 $/MTok 1920×1080 token 数 每千次 $ 3840×2160 token 数 每千次 $
Haiku 4.5 standard $1 1,560 $1.56 1,560 $1.56
Sonnet 4.6 standard $3 1,560 $4.68 1,560 $4.68
Opus 4.6 standard $5 1,560 $7.80 1,560 $7.80
Opus 4.7 high $5 2,691 $13.46 4,784 $23.92
Haiku 5.5(提示词 ≤100K) high $0.10 2,691 $0.27 4,784 $0.48
Sonnet 5.5 high $2 2,691 $5.38 4,784 $9.57
Opus 5.5 high $4 2,691 $10.76 4,784 $19.14

Sonnet 那几行值得仔细看。Sonnet 5.5 的输入价格比 Sonnet 4.6 低三分之一,但一张 4K 截图在它上面的花费大约是后者的两倍。每个 token 是便宜了,可同一张图片现在要消耗大约三倍的 token。


同一张截图、同一个文件:模型的分辨率档位决定了账单有多重。

如果不需要额外细节,发送前先缩小图片。Anthropic 的文档说得很直接:不需要高保真时就降采样,自己调整尺寸来降低延迟。从坐标指南里复制 resizedSize(附带了 TypeScript 版本),就能在任何模型上把截图控制在旧版标准预算内:

// resizedSize() is Anthropic's reference function,
// copied from the vision-coordinates guide.
const STANDARD = { edge: 1568, tokens: 1568 };

async function pinToStandard(src: Buffer) {
  const meta = await sharp(src).metadata();
  const [w, h] = resizedSize(
    meta.width ?? 0,
    meta.height ?? 0,
    STANDARD.edge,
    STANDARD.tokens,
  );
  return sharp(src)
    .resize({ width: w, height: h, fit: "fill" })
    .png()
    .toBuffer();
}

但也别盲目操作。同一份文档指出,高分辨率档位是为计算机操作、截图理解和密集文档准备的,而缩小图片时最先损失的正是小字。拿你真实的截图分别跑两种尺寸,核对回答,再决定预算。

截图类应用还要多守几条规则。单次请求超过 20 张图片会触发更严格的单图尺寸限制,视觉文档建议长宽都控制在 3,000 px 以内,以确保在各平台都不越界。返回给计算机操作和浏览器操作工具的截图一旦超出模型限制,会直接报校验错误,而不会被缩小。如果服务端静默缩放会破坏你的流水线,就在图片块上设置 "transformations": { "oversized_image": "error" }:这样 API 和 token 计数端点会直接拒绝该图片,而不是缩小它,详见坐标指南。

真正省事的习惯其实很朴素。在带截图的功能上线前,用你实际部署的那个模型 ID 对一张真实截图做一次计数,把单图数字写在功能旁边,换模型时重新计数。


如果这篇文章对你有帮助

单次请求的 token 成本,是每个能跑起来的 LLM 应用首先要算对的事之一,也是AI That Answers重点讲的内容:用 TypeScript 写你的第一个 LLM 应用,从提示词、结构化输出,到在用户替你发现之前就搞清楚每次调用花多少钱。如果你希望上面那个截图功能上线时带着预算而不是惊吓,我会从这本书开始。

这是AI in TypeScript系列的第一本,全套五本,从第一次调用 LLM 一直到生产环境中的 Agent:整个系列都在这里。

——

广告 广告
🧑‍💻

zhirenhun

一个热爱技术的程序员,喜欢分享前沿AI知识和开发经验。

ai typescript llm claude