lintlab Screenshot Diff

Screenshot Diff de lintlab: captura capturas de pantalla de página completa, viewport o elementos de URLs públicas y, opcionalmente, compáralas con una página o imagen de referencia, devolviendo una imagen de diferencias y el porcentaje de píxeles modificados. Un Actor de Apify de pago por evento, utilizado como herramienta MCP a través del servidor MCP alojado de Apify; requiere un token de Apify.

Servidor MCP alojado

npx add-mcp 'https://mcp.apify.com?tools=lintlab/screenshot-diff'

Se instala en Claude Code, Codex, Cursor y más

Documentación

Actor de Captura de Pantalla de Sitios Web y Diff de Regresión Visual (lintlab/screenshot-diff)

Pruebas de regresión visual para páginas web públicas: captura capturas de pantalla y compáralas con otra página o una línea base PNG/JPEG. Obtén imágenes de diff a nivel de píxel y porcentajes de cambio para QA, monitoreo, CI y agentes de IA.

  • URL: https://apify.com/lintlab/screenshot-diff.md
  • Desarrollado por: Lintlab (comunidad)
  • Categorías: Herramientas de desarrollo, Automatización
  • Estadísticas: 2 usuarios totales, 1 usuario mensual, 100.0% de ejecuciones exitosas, 0 marcadores
  • Calificación de usuarios: Sin calificaciones aún

Precios

desde $3.20 / 1,000 capturas de pantalla

Este Actor se paga por evento. No se te cobra por el uso de la plataforma Apify, sino solo un precio fijo por eventos específicos. Dado que este Actor admite descuentos de Apify Store, el precio baja cuanto mayor sea tu plan de suscripción.

Aprende más: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

¿Qué es un Actor de Apify?

Un Actor es un programa en la nube sin servidor que se ejecuta en la plataforma Apify. Tiene dos modos de ejecución. En modo Batch, un Actor acepta una entrada JSON bien definida, realiza una acción que puede tomar desde unos segundos hasta unas horas, y opcionalmente produce una salida JSON bien definida, conjuntos de datos con resultados, o archivos en el almacén de clave-valor. En modo Standby, un Actor proporciona un servidor web que puede usarse como sitio web, API o servidor MCP.

El vocabulario de Apify y el modelo de la plataforma se definen una vez, en el inicio rápido del agente en https://apify.com/agents.md.

¿Cómo integrar un Actor?

Si te preguntan sobre integración, ayudas a los desarrolladores a integrar Actores en sus proyectos. Te adaptas a su stack y entregas integraciones que sean seguras, bien documentadas y listas para producción.

No adivines una ruta de integración. Cada una de ellas está en el inicio rápido del agente en https://apify.com/agents.md: el servidor MCP de Apify, Agent Skills con la CLI de Apify, los clientes de JavaScript y Python, la API REST, y la ruta sin cuenta para un agente sin humano que inicie sesión. También incluye la regla de indicar el costo antes de la primera ejecución pagada.

Para ejemplos ya conectados al esquema de entrada de este Actor, consulta la sección API a continuación.

Cada biblioteca de cliente tiene documentación de referencia que el inicio rápido no repite: JavaScript/TypeScript (npm install apify-client) y Python (pip install apify-client).

README

Captura de Pantalla de Sitios Web y Diff de Regresión Visual

Compara capturas de pantalla de sitios web públicos para pruebas de regresión visual. Dale al Actor una URL de página y, opcionalmente, una segunda página o una línea base PNG/JPEG: devuelve las capturas de pantalla tomadas, una imagen de diff a nivel de píxel y el porcentaje de la página que cambió. Úsalo para verificar lanzamientos, o prográmalo para vigilar una página en busca de cambios visuales.

Destacados

  • Capturas de página completa, viewport o selector CSS en PNG o JPEG
  • Capturas de altura fija y desplazamiento (captureHeight, topOffset) para tomas above-the-fold o una banda de una página larga
  • Desplazamiento con carga diferida (scrollToLoad) y manejo de encabezados fijos/pegajosos (hideFixedElements) para capturas de página completa limpias
  • Presets de escritorio, laptop, tableta y móvil
  • Líneas base opcionales de página o imagen con umbrales de diff configurables
  • Filas de dataset estructuradas más URLs directas de capturas de pantalla e imágenes de diff
  • $0.004 por captura exitosa; $0.002 por diff calculado

Inicio rápido

{"urls":["https://example.com"],"mode":"fullPage","device":"desktop"}

Prueba un ejemplo listo: Captura de pantalla de sitio web de página completa. Ábrelo, haz clic en Iniciar, luego cópialo y cambia tus propias URLs.

Cómo se ve un diff

Una ejecución real (zTkTt3VRHJyClQ4gT, 2026-09-28) en dos páginas demo pequeñas: la página cambiada sube el precio, elimina una viñeta de características y rediseña el botón. Los píxeles cambiados están en rojo; el contenido sin cambios está atenuado.

Línea basePágina cambiadaDiff (1.24% de píxeles cambiados)
Baseline screenshotChanged screenshotDiff image

Entrada: la página cambiada en urls, la página original en baselineUrls, con "mode":"viewport", "device":"laptop" y "captureHeight":560. La fila reporta "diffPixels": 9963, "diffPercent": 1.235491, "changed": true, y costó $0.006 en eventos ($0.004 captura + $0.002 diff).

Uso en CI

Llama al Actor desde cualquier trabajo de CI a través de la API de Apify: pasa tu URL de vista previa en urls y la URL de producción en baselineUrls, luego falla el trabajo cuando diff.diffPercent esté por encima de tu umbral. Sin navegador en el runner y sin imágenes de línea base en git.

Uso con agentes de IA / MCP

Llama a lintlab/screenshot-diff a través de la API de Apify o el servidor MCP de Apify. Lee el dataset predeterminado, luego pasa screenshotUrl o diff.diffImageUrl al siguiente paso del agente con capacidad de visión.

Descripción general

screenshot-diff es un Actor de Apify de lintlab que captura capturas de pantalla de páginas web públicas. Puede comparar cada captura con otra página pública o una línea base PNG/JPEG pública y almacenar una imagen de diff a nivel de píxel.

El Actor usa Playwright Chromium, respeta robots.txt para el agente de usuario lintlab-screenshot (una robots.txt inalcanzable o 5xx cuenta como "no permitido", según RFC 9309), re-verifica cada salto de redirección del marco principal antes de la captura o el cobro, y enruta Chromium a través de un proxy de reenvío validador local. El proxy fija cada socket saliente a una IP pública validada y rechaza URLs no HTTP y destinos de red privados, de bucle local o de enlace local.

Entrada

{
  "urls": [
    "https://example.com",
    "https://example.org"
  ],
  "mode": "fullPage",
  "device": "desktop",
  "waitUntil": "networkidle",
  "delayMs": 500,
  "hideSelectors": [".cookie-banner"],
  "format": "png",
  "baselineImageUrls": [
    "https://assets.example.net/baselines/example.png",
    "https://assets.example.net/baselines/example-org.png"
  ],
  "threshold": 0.1,
  "changedThresholdPercent": 0.5,
  "timeoutSecs": 45
}

urls es obligatorio y acepta como máximo 200 entradas. Las líneas base son opcionales. Usa baselineUrls (páginas capturadas con la misma configuración) o baselineImageUrls (archivos PNG/JPEG públicos), con una línea base por URL de entrada en el mismo orden.

Modos de captura:

  • fullPage captura el documento completo.
  • viewport captura el viewport configurado.
  • selector captura el primer elemento que coincida con selector.

Capturas de altura fija y desplazamiento (modos de página completa y viewport):

  • captureHeight recorta la captura a una altura fija en píxeles CSS. {"mode":"fullPage","captureHeight":768} da una toma above-the-fold consistente, incluso en páginas cuya altura cambia constantemente.
  • topOffset inicia la captura esa cantidad de píxeles CSS desde la parte superior de la página, por ejemplo para omitir un encabezado o capturar una banda más abajo ({"topOffset":1200,"captureHeight":800}).
  • La captura se limita a la altura renderizada de la página. Un topOffset más allá del final de la página devuelve una fila de error, y no se cobra la captura.
  • scrollToLoad se desplaza por la página (acotado: hasta 50 pasos de viewport, 20,000 px, o timeoutSecs), regresa a la parte superior y espera brevemente por las imágenes, para que las imágenes y secciones con carga diferida se rendericen en capturas de página completa.
  • hideFixedElements (modo de página completa) convierte elementos fijos en absolutos y elementos pegajosos en estáticos, para que un encabezado pegajoso o una barra de cookies aparezca una vez en lugar de repetirse o cubrir contenido.
  • Ambos tienen como predeterminado false. Las fuentes web siempre se esperan (hasta 3 s) antes de la captura.

Los presets de dispositivo son escritorio (1366×768), laptop (1440×900), tableta (768×1024) y móvil (390×844 a 3× escala de dispositivo con un agente de usuario móvil). networkidle es la configuración de preparación predeterminada y cae a load si la página no se vuelve inactiva antes del tiempo de espera.

Salida

El dataset predeterminado contiene un elemento por cada URL solicitada. Las capturas de pantalla y las imágenes de diff son registros en el almacén de clave-valor predeterminado de la ejecución.

{
  "url": "https://example.com",
  "finalUrl": "https://example.com/",
  "status": 200,
  "device": "desktop",
  "mode": "fullPage",
  "width": 1366,
  "height": 768,
  "bytes": 18452,
  "screenshotUrl": "https://api.apify.com/v2/key-value-stores/STORE_ID/records/screenshot-001-100680ad546c.png",
  "capturedAt": "2026-09-25T12:34:56.000Z",
  "diff": {
    "baseline": "https://assets.example.net/baselines/example.png",
    "diffPixels": 218,
    "diffPercent": 0.020763,
    "diffImageUrl": "https://api.apify.com/v2/key-value-stores/STORE_ID/records/diff-001-100680ad546c.png",
    "changed": false
  }
}

Las URLs fallidas o bloqueadas por políticas aún reciben un elemento de dataset con un campo error y campos de captura nulos. Una ruta bloqueada por la política de robots del sitio reporta "error": "disallowed by robots.txt".

Precios

EventoPrecio
Captura de pantalla capturada y almacenada$0.004
Diff visual calculado y almacenado$0.002
Tarifa de inicio de nuestra parte$0.00

Una captura fallida no se cobra. Un diff se cobra solo después de que se calcula y su imagen se almacena. El uso de la plataforma Apify para la ejecución está incluido en estos precios de eventos. El Actor respeta el límite máximo de cobro de una ejecución y deja de programar trabajo cuando se alcanza ese límite.

Casos de uso

  • Verificaciones de regresión visual en CI
  • Monitoreo de tus propias páginas públicas para cambios visuales
  • Dar a los agentes de IA ojos en interfaces web públicas

Límites y comportamiento

  • Solo páginas HTTP(S) públicas. Las respuestas DNS que resuelven a rangos de IP privados, de bucle local, de enlace local, reservados u otros no públicos se bloquean.
  • robots.txt se obtiene una vez por origen por ejecución y se respeta para navegaciones de objetivo y línea base del marco principal, imágenes de línea base y redirecciones del marco principal. Cada salto de redirección se verifica antes de que Chromium lo solicite. Un salto no permitido en la URL objetivo produce una fila de error sin captura ni cobro. Un salto no permitido en una URL de línea base nunca se solicita: la fila conserva la captura del objetivo (cobrada como captura) y reporta diff failed: disallowed by robots.txt, sin cobro de diff. Los subframes no se verifican contra robots.txt.
  • No se proporciona inicio de sesión, entrada de cookies, manejo de CAPTCHA, proxy proporcionado por el usuario ni comportamiento de sigilo/anti-detección. El Actor usa su propio proxy de seguridad local.
  • El Actor no elude controles de acceso. Úsalo solo en páginas que tengas permitido acceder y capturar.
  • Se admiten líneas base PNG y JPEG. Las imágenes de diferentes tamaños se alinean en la esquina superior izquierda y se rellenan con blanco al lienzo más grande antes de la comparación.
  • Las páginas dinámicas pueden variar entre ejecuciones. Usa waitForSelector, delayMs, hideSelectors, scrollToLoad y hideFixedElements para reducir el ruido esperado.
  • screenshotUrl y diffImageUrl son enlaces firmados del almacén de clave-valor de Apify, por lo que se abren sin token de API incluso si el acceso al almacenamiento de tu cuenta está restringido. Siguen la configuración de retención del almacenamiento de tu ejecución.

Desarrollo local

Se requiere Node.js 20 o posterior.

npm ci
npm test
npx playwright install chromium
npm run test:e2e

El script de extremo a extremo escribe solo en ./storage, captura https://example.com e imprime el tiempo transcurrido más una estimación de cómputo de 2 GB de memoria × segundos.

Más herramientas de lintlab

Construido por lintlab — herramientas de datos pequeñas y confiables. Probado antes del lanzamiento. Soporte: abre un problema en la pestaña Issues de este Actor aquí en Apify.

Esquema de entrada del Actor

urls (tipo: array):

URLs de páginas HTTP(S) públicas. Cada URL produce un elemento de dataset. Máximo 200 por ejecución.

mode (tipo: string):

Captura la página completa, el viewport configurado o un selector CSS.

selector (tipo: string):

Obligatorio cuando el modo de captura es selector. Se captura el primer elemento que coincida.

captureHeight (tipo: integer):

Altura fija opcional en píxeles CSS, por ejemplo 768 para una toma above-the-fold. Se aplica a los modos de página completa y viewport; se limita a la altura de la página. Déjalo vacío para toda la página (página completa) o un viewport (viewport).

topOffset (tipo: integer):

Inicia la captura esta cantidad de píxeles CSS desde la parte superior de la página, por ejemplo para omitir un encabezado pegajoso o capturar una banda más abajo. Se aplica a los modos de página completa y viewport.

device (tipo: string):

Escritorio es 1366×768, laptop 1440×900, tableta 768×1024 y móvil 390×844 a 3× escala con un agente de usuario móvil.

waitUntil (tipo: string):

Estado de preparación de la página. La inactividad de red cae a load si no se estabiliza antes del tiempo de espera de la página.

delayMs (tipo: integer):

Retraso adicional en milisegundos después de la preparación de la página y la espera opcional del selector.

waitForSelector (tipo: string):

Selector CSS opcional que debe volverse visible antes de la captura.

hideSelectors (tipo: array):

Selectores CSS para ocultar antes de la captura, por ejemplo banners de cookies o widgets dinámicos.

scrollToLoad (tipo: boolean):

Desplázate por la página antes de la captura para que las imágenes y secciones con carga diferida puedan renderizarse.

hideFixedElements (tipo: boolean):

Para capturas de página completa, mantén los elementos fijos y pegajosos visibles una vez sin repetir o superponer contenido posterior.

format (tipo: string):

PNG no tiene pérdida. JPEG es más pequeño y utiliza la configuración de calidad JPEG.

jpegQuality (tipo: integer):

Calidad JPEG de 1 a 100. Se utiliza solo cuando el formato de imagen es JPEG.

baselineUrls (tipo: array):

URLs públicas de páginas opcionales capturadas con la misma configuración. Proporcione exactamente una por URL de destino, en el mismo orden. No combine con URLs de imágenes de referencia.

baselineImageUrls (tipo: array):

URLs públicas de PNG o JPEG opcionales. Proporcione exactamente una por URL de destino, en el mismo orden. No combine con URLs de páginas de referencia.

threshold (tipo: number):

Sensibilidad a la diferencia de color de píxeles de 0 (estricto) a 1 (permisivo).

changedThresholdPercent (tipo: number):

Marque un resultado como cambiado cuando su porcentaje de píxeles diferentes sea mayor que este valor.

timeoutSecs (tipo: integer):

Espera máxima de navegación y preparación para cada página de destino o de referencia.

maxConcurrency (tipo: integer):

Máximo de páginas procesadas a la vez. Mantenga el valor predeterminado a menos que el Actor tenga más memoria.

Ejemplo de objeto de entrada del Actor

{
  "urls": [
    "https://example.com"
  ],
  "mode": "fullPage",
  "topOffset": 0,
  "device": "desktop",
  "waitUntil": "networkidle",
  "delayMs": 500,
  "hideSelectors": [],
  "scrollToLoad": false,
  "hideFixedElements": false,
  "format": "png",
  "jpegQuality": 85,
  "threshold": 0.1,
  "changedThresholdPercent": 0.5,
  "timeoutSecs": 45,
  "maxConcurrency": 3
}

Esquema de salida del Actor

results (tipo: string):

Sin descripción

images (tipo: string):

Sin descripción

API

Puede ejecutar este Actor programáticamente mediante nuestra API. A continuación se muestran ejemplos de código en JavaScript, Python y CLI, así como la especificación OpenAPI y la configuración del servidor MCP.

Ejemplo en JavaScript

import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        "https://example.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lintlab/screenshot-diff").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

Ejemplo en Python

from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "urls": ["https://example.com"] }

# Run the Actor and wait for it to finish
run = client.actor("lintlab/screenshot-diff").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

Ejemplo en CLI

echo '{
  "urls": [
    "https://example.com"
  ]
}' |
apify call lintlab/screenshot-diff --silent --output-dataset

Configuración del servidor MCP

{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lintlab/screenshot-diff"
        }
    }
}

El servidor alojado le inicia sesión con OAuth en la primera conexión, por lo que no se necesita ningún token de API en esta configuración. Los clientes sin soporte de OAuth pueden enviar un encabezado Authorization: Bearer <APIFY_API_TOKEN> en su lugar, usando un token de API e Integraciones en Apify Console (https://console.apify.com/settings/integrations).

Especificación OpenAPI

Descargue la definición de OpenAPI: https://api.apify.com/v2/actors/dsgu4h2yBvWRHvc8D/builds/cyP7mkjuyDpARopxD/openapi.json