惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
aimingoo的专栏
aimingoo的专栏
月光博客
月光博客
博客园 - Franky
Martin Fowler
Martin Fowler
U
Unit 42
阮一峰的网络日志
阮一峰的网络日志
Recent Announcements
Recent Announcements
The Cloudflare Blog
博客园 - 聂微东
酷 壳 – CoolShell
酷 壳 – CoolShell
宝玉的分享
宝玉的分享
J
Java Code Geeks
B
Blog RSS Feed
博客园 - 三生石上(FineUI控件)
MongoDB | Blog
MongoDB | Blog
腾讯CDC
博客园_首页
博客园 - 司徒正美
D
DataBreaches.Net
I
InfoQ
GbyAI
GbyAI
IT之家
IT之家
罗磊的独立博客

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
I built a $0.0005 screenshot cropper that saves AI agents...
aaroncarlisle94 · 2026-06-25 · via DEV Community
Cover image for I built a $0.0005 screenshot cropper that saves AI agents 95% on vision LLM costs

aaroncarlisle94

If you're building AI agents that work with browser screenshots, you already know the pain.

You take a full 1920×1080 screenshot, pass it to GPT-4o or Claude, and watch your token bill climb — while the model downscales the image anyway and blurs the exact text you needed it to read.

There's a better way.

The problem

Vision LLMs are expensive for two reasons when you feed them full screenshots:

  1. Token cost — a full screenshot can cost 10–20x more tokens than a small crop
  2. Accuracy loss — models internally downscale large images, blurring fine text, labels, and UI elements

But your agent already knows where to look. Browser automation tools like Playwright and Puppeteer give you getBoundingClientRect() — the exact pixel coordinates of any element on screen.

So why are you sending the whole screenshot?

The solution

I built a stateless pay-per-use API that takes a screenshot and pixel coordinates, and returns just the cropped element as a lossless PNG — ready to pass directly to your vision LLM.

POST /crop
{
  "image":  "<base64 screenshot>",
  "x":      120,
  "y":      45,
  "width":  640,
  "height": 80
}

Returns:

{
  "success": true,
  "data": {
    "base64": "iVBORw0KGgo...",
    "mime":   "image/png",
    "width":  640,
    "height": 80,
    "bytes":  4821
  }
}

A 4KB crop instead of a 2MB screenshot. Same information. 95% fewer tokens.

How payment works

Here's where it gets interesting. The API uses the x402 payment protocol — HTTP's long-dormant 402 Payment Required status code, finally put to use.

There are no API keys. No accounts. No subscriptions. The agent pays $0.0005 USDC per crop on Base L2 automatically.

The flow:

1. Agent POSTs to /crop (no payment header)
   ← 402 with payment instructions in headers

2. Agent transfers 0.0005 USDC to recipient wallet on Base
   (near-zero gas, ~2 second settlement)

3. Agent POSTs again with x-payment-tx-hash header
   ← 200 with cropped PNG

The entire exchange happens inside the HTTP request cycle. No human intervention. No billing dashboard. The money lands directly in the operator's wallet on-chain.

Real agent integration

Here's what using it looks like in a Playwright agent:

import { chromium } from 'playwright';
import { readFileSync } from 'fs';

const browser = await chromium.launch();
const page    = await browser.newPage();
await page.goto('https://example.com/dashboard');

// Take screenshot
await page.screenshot({ path: 'screen.png' });
const imageB64 = readFileSync('screen.png').toString('base64');

// Get element coordinates
const rect = await page.$eval('.price-display', el => el.getBoundingClientRect().toJSON());

// Probe the API for payment instructions
const probe = await fetch('https://x402-vision-cropper.onrender.com/crop', {
  method:  'POST',
  headers: { 'Content-Type': 'application/json' },
  body:    JSON.stringify({
    image:  imageB64,
    x:      Math.floor(rect.x),
    y:      Math.floor(rect.y),
    width:  Math.floor(rect.width),
    height: Math.floor(rect.height),
  }),
});

// → 402 response with payment details in headers
const recipient = probe.headers.get('x-payment-recipient');
const amount    = probe.headers.get('x-payment-price-usdc');

// Pay on Base L2 using viem
const txHash = await sendUsdc({ recipient, amount }); // your wallet logic here

// Resubmit with payment proof
const result = await fetch('https://x402-vision-cropper.onrender.com/crop', {
  method:  'POST',
  headers: {
    'Content-Type':       'application/json',
    'x-payment-tx-hash':  txHash,
  },
  body: JSON.stringify({
    image:  imageB64,
    x:      Math.floor(rect.x),
    y:      Math.floor(rect.y),
    width:  Math.floor(rect.width),
    height: Math.floor(rect.height),
  }),
});

const { data } = await result.json();

// Pass the tiny crop to your vision LLM instead of the full screenshot
const response = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages: [{
    role: 'user',
    content: [
      { type: 'image_url', image_url: { url: `data:${data.mime};base64,${data.base64}` } },
      { type: 'text', text: 'What is the price shown?' }
    ]
  }]
});

The architecture

The server is intentionally minimal:

  • Fastify on Node.js — low memory footprint
  • Sharp for image processing — in-RAM only, no disk writes
  • Zero persistent storage — every request is stateless, data exists only for the duration of the request
  • Runs on a 512MB single-CPU container on Render

The entire codebase is about 400 lines across 7 files. No database. No session state. No auth layer beyond the payment itself.

Try it

The API is live now:

# Check it's running
curl https://x402-vision-cropper.onrender.com/health

# Trigger the payment challenge
curl -X POST https://x402-vision-cropper.onrender.com/crop \
  -H "Content-Type: application/json" \
  -d '{"image":"'"$(python3 -c "print('A'*200)")"'","x":0,"y":0,"width":10,"height":10}'

Machine-readable docs for agents: https://x402-vision-cropper.onrender.com/llms.txt

What I learned building this

x402 is genuinely exciting but very early. The protocol works cleanly — payment instructions in headers, proof in the retry, settlement on-chain. But the agent ecosystem is still catching up. Most frameworks don't have native wallet support yet.

Stateless by design is underrated. No database means no breach, no GDPR headache, no backup strategy, no connection pooling. Every request lives and dies in RAM. For a high-throughput API that processes sensitive screenshot data this is the right architecture.

The unit economics make sense at scale. At $0.0005 per crop the service costs less than a rounding error compared to what it saves on vision tokens. The challenge isn't pricing — it's volume.


If you're building browser agents or anything that feeds screenshots to vision models, give it a try. And if you're building in the x402 / agentic payments space I'd love to hear what you're working on.