Notas · 21 de octubre de 2026 · 5 min de lectura

Captura de pantalla de una web con Node.js, Python y PHP

Necesitás una imagen de una página web desde tu código: para una miniatura, un reporte, un archivo de evidencia o un test visual. En tu máquina sale en cinco minutos; el problema aparece cuando eso tiene que correr en un servidor, todos los días, sin que nadie lo mire.

Hay dos caminos: levantar vos un navegador headless o pedirle la captura a una API. Vamos con los dos, con código que podés copiar y pegar.

Opción 1: hacelo vos con Puppeteer o Playwright

Puppeteer (Node.js) y Playwright (Node.js, Python y otros) controlan un Chrome sin ventana. Sacar una captura es corto:

// captura-puppeteer.mjs
// Instalación: npm install puppeteer
import puppeteer from "puppeteer";

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 800 });
await page.goto("https://example.com", { waitUntil: "networkidle2", timeout: 30000 });
await page.screenshot({ path: "captura.png", fullPage: true });
await browser.close();

Lo mismo en Python con Playwright:

# Instalación: pip install playwright && playwright install chromium
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page(viewport={"width": 1280, "height": 800})
    page.goto("https://example.com", wait_until="networkidle", timeout=30000)
    page.screenshot(path="captura.png", full_page=True)
    browser.close()

Funciona. Los dolores aparecen cuando lo llevás a producción:

Si sacás pocas capturas y ya tenés un servidor con Node, esta opción está perfecta. Si no, seguí leyendo.

Opción 2: pedirle la captura a una API

Una API de capturas hace lo mismo, pero el Chrome corre en otro lado: vos mandás la URL y recibís la imagen. Los ejemplos usan screenshot.com.ar: GET /v1/capture devuelve la imagen directamente y te autenticás con el header X-API-Key. El plan gratis tiene 100 capturas por mes, sin tarjeta.

Los parámetros que vas a usar más seguido:

Node.js (con fetch)

Necesitás Node 18 o superior, que ya trae fetch. Guardalo como captura.mjs y corré node captura.mjs:

// captura.mjs
import { writeFile } from "node:fs/promises";

const params = new URLSearchParams({
  url: "https://example.com",
  width: "1280",
  full_page: "true",
  format: "webp",
});

const res = await fetch(`https://screenshot.com.ar/v1/capture?${params}`, {
  headers: { "X-API-Key": "TU_API_KEY" },
});

if (!res.ok) {
  throw new Error(`Error ${res.status}: ${await res.text()}`);
}

await writeFile("captura.webp", Buffer.from(await res.arrayBuffer()));
// Si salió de cache no gastó nada y no trae este header
console.log("Listo. Capturas que te quedan:", res.headers.get("x-quota-remaining") ?? "(salió de cache)");

Python (con requests)

# Instalación: pip install requests
import requests

res = requests.get(
    "https://screenshot.com.ar/v1/capture",
    params={
        "url": "https://example.com",
        "width": 1280,
        "full_page": "true",
        "format": "webp",
    },
    headers={"X-API-Key": "TU_API_KEY"},
    timeout=60,
)

if not res.ok:
    raise SystemExit(f"Error {res.status_code}: {res.text}")

with open("captura.webp", "wb") as f:
    f.write(res.content)

print("Listo. Salió de cache:", res.headers.get("X-Cache"))

PHP (con curl)

Funciona en cualquier hosting con la extensión curl, que viene activada casi siempre:

<?php
$params = http_build_query([
    'url' => 'https://example.com',
    'width' => 1280,
    'full_page' => 'true',
    'format' => 'webp',
]);

$ch = curl_init('https://screenshot.com.ar/v1/capture?' . $params);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['X-API-Key: TU_API_KEY'],
    CURLOPT_TIMEOUT => 60,
]);

$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if ($body === false || $status !== 200) {
    exit("Error $status: " . ($body === false ? curl_error($ch) : $body) . "\n");
}

file_put_contents('captura.webp', $body);
echo "Listo\n";

En los tres casos, no dejes la clave escrita en el código que subís a un repositorio: leela de una variable de entorno (process.env, os.environ o getenv()).

Detalles que te ahorran un rato

Bonus: el texto de la página en vez de la imagen

Si lo que querés es el contenido (para guardarlo, compararlo o pasárselo a un modelo de IA), está GET /v1/read: abre la página una vez y devuelve un JSON con el contenido principal en markdown, sin menús ni publicidad, y opcionalmente la captura en base64:

curl "https://screenshot.com.ar/v1/read?url=https://example.com&screenshot=false" \
  -H "X-API-Key: TU_API_KEY"

¿Cuál conviene?

Si ya tenés la infraestructura y sacás pocas capturas, Puppeteer o Playwright alcanzan. Si no querés mantener un Chrome en el servidor, o estás en PHP, la API te lo resuelve con un pedido HTTP. Con 100 capturas gratis por mes podés probarla sin compromiso, y si te quedás corto los planes se pagan en pesos: mirá los precios. Todos los parámetros están en la documentación.

Probá screenshot.com.ar gratis

100 capturas por mes sin tarjeta, por API o por MCP. Planes en pesos con Mercado Pago.

Crear mi API key