
Aloísio Vítor
Image Processing Expert

Si alguna vez has intentado extraer precios, datos de productos o contenido de páginas protegidas, ya sabes que la parte difícil no es solo cargar la URL. El flujo de trabajo también debe resolver los captchas del sitio, enviar el token resuelto de la manera que el sitio espere y luego extraer los datos correctos de la respuesta protegida.
Es por eso que los ejemplos simples "resolver captchas y listo" no son suficientes para la automatización real. Un sitio puede esperar el token en un encabezado, en el cuerpo del formulario, en un payload JSON, en una cadena de consulta, en una cookie o en otro campo específico de la aplicación. Puede usar reCAPTCHA, Turnstile o otro desafío de captcha completamente diferente. Y una vez que regrese la respuesta protegida, los selectores y la lógica de salida aún deben coincidir con tu objetivo.
En esta guía, aprenderás a construir scrapers para sitios protegidos por captcha en n8n usando CapSolver. La explicación principal se basa en el flujo de trabajo del repositorio Scraping — Price & Product Details — CapSolver + Schedule + Webhook, pero el mismo patrón se puede adaptar para:
Este artículo trata sobre automatización práctica y autorizada en objetivos que posees, gestionas o estás autorizado a probar.
Importante: Estos flujos de trabajo son ejemplos y plantillas iniciales, no recetas universales. Debes esperar modificar la configuración de captcha, el método de envío del token, la carga de la solicitud, los encabezados, las cookies, los selectores y la lógica de salida para que coincidan con cada sitio específico.
El ejemplo principal de este artículo es una plantilla de scraper para objetivos fijos que ahora soporta dos modos de activación:
En la plantilla predeterminada del repositorio, ese flujo de trabajo:
x-recaptcha-tokenprice y productName$workflow.staticDataEl mismo patrón puede convertirse en:
Todas las plantillas de este repositorio siguen el mismo esqueleto reutilizable:
activación -> resolver captchas -> enviar solicitud protegida -> extraer resultado -> comparar/guardar/salida
Esta estructura se adapta a varios casos de uso legítimos:
| Caso de uso | ¿Qué cambia? |
|---|---|
| Extracción de datos | Extraer campos de precio y compararlos con el tiempo |
| Extracción de datos de productos | Extraer campos como título, SKU, vendedor, stock o descripción |
| Verificación de stock | Comparar texto de disponibilidad, cantidad o estado del botón de compra |
| Inicio de sesión en tu propia cuenta | Enviar el token resuelto con tu solicitud de inicio de sesión y verificar el éxito |
| Recuperación de contenido protegido | Obtener contenido restringido y devolver los campos extraídos |
| Extracción disparada por webhook | Deja que otro servicio active el objetivo configurado fijo a demanda |
La estructura sigue siendo reutilizable, pero los detalles de implementación reales pueden variar en cada sitio. En la práctica, los usuarios deben tratar cada flujo de trabajo aquí como un ejemplo y luego adaptar la configuración de resolución, la forma de la solicitud, la ubicación del token y la lógica de extracción al objetivo que están automatizando.
El flujo de trabajo principal anterior recupera contenido de página sin procesar y compara precios. Los siguientes flujos extienden el mismo patrón de resolución de captcha — Activación → Resolver Captcha → Enviar Solicitud Protegida → Evaluar Resultado — a casos de uso específicos. Cada uno requiere los mismos requisitos previos: una instancia de n8n, una credencial de CapSolver y los parámetros de captcha del objetivo.
| Flujo de trabajo | Propósito |
|---|---|
Scraping — Price & Product Details — CapSolver + Schedule + Webhook |
Plantilla de programación + webhook para objetivos fijos que resuelve reCAPTCHA v3, envía el token en x-recaptcha-token, extrae price y productName, compara valores con $workflow.staticData y puede usarse para extracción, extracción de detalles de producto o verificaciones similares en páginas protegidas de productos |
Nota de activación: Esta plantilla se importa como
active: false. La ruta del webhook no está activa hasta que configures los marcadores de posición, elige tu credencial de CapSolver y activas el flujo de trabajo en n8n.
Antes de comenzar, asegúrate de tener:
Para el ejemplo principal de este artículo, se asume que el objetivo utiliza reCAPTCHA, por lo que los valores clave son:
websiteURLwebsiteKeypageAction para reCAPTCHA v3Importante: El recorrido para identificar parámetros a continuación está intencionalmente limitado a ejemplos de reCAPTCHA. Los objetivos reales pueden usar un tipo de desafío completamente diferente, como Cloudflare Turnstile, Cloudflare Challenge, GeeTest, DataDome, AWS WAF o MTCaptcha, y en ese caso la configuración del nodo de resolución, los campos requeridos y el patrón de solicitud protegida serán diferentes.
Para páginas protegidas por reCAPTCHA, los valores principales suelen ser:
| Parámetro | Qué significa |
|---|---|
websiteURL |
La URL donde se muestra o se requiere el captcha |
websiteKey |
La clave pública utilizada por la página |
pageAction |
La cadena de acción esperada por reCAPTCHA v3 |
En la plantilla de monitoreo de precios del repositorio, el nodo de CapSolver está configurado con:
operation: reCAPTCHA v3websiteURL: https://YOUR-TARGET-SITE.com/product-pagewebsiteKey: YOUR_SITE_KEY_HEREpageAction: view_productAl inspeccionar un objetivo de reCAPTCHA, verifica:
pageActionImportante: Esta no es una sección de detección de captchas universal. Si el objetivo utiliza un tipo de desafío diferente, como Cloudflare Turnstile, Cloudflare Challenge, GeeTest, DataDome, AWS WAF o MTCaptcha, deberás cambiar tanto la configuración de CapSolver como la solicitud HTTP que envía el token resuelto.
El flujo de trabajo del repositorio Scraping — Price & Product Details — CapSolver + Schedule + Webhook ahora soporta dos caminos de activación para objetivos fijos:
Cada 6 horas para revisiones recurrentesWebhook Trigger para ejecuciones a demandaAmbos caminos usan los mismos marcadores de posición de objetivo y la misma lógica de scraper. La versión de webhook simplemente termina en Respond to Webhook para que el llamador obtenga el payload de alerta final o el payload sin cambios como JSON.
El camino de programación usa estos nodos:
Every 6 HoursSolve reCAPTCHA v3Fetch Product PageExtract DataCompare DataData Changed?Build AlertNo ChangeEl camino de webhook duplica la misma lógica para el mismo objetivo fijo:
Webhook TriggerSolve reCAPTCHA v3 [Webhook]Fetch Product Page [Webhook]Extract Data [Webhook]Compare Data [Webhook]Data Changed? [Webhook]Build Alert [Webhook]No Change [Webhook]Respond to WebhookUsa programación cuando quieres revisiones recurrentes, como extracción o verificación de stock.
Usa webhook cuando otro flujo de trabajo, servicio o aplicación debe activar el mismo objetivo configurado a demanda.
La plantilla usa:
| Configuración | Valor |
|---|---|
| Operación | reCAPTCHA v3 |
websiteURL |
https://YOUR-TARGET-SITE.com/product-page |
websiteKey |
YOUR_SITE_KEY_HERE |
pageAction |
view_product |
El token resuelto se envía en un encabezado de solicitud:
| Encabezado | Valor |
|---|---|
user-agent |
Agente de usuario estilo navegador |
x-recaptcha-token |
{{ $json.data.solution.gRecaptchaResponse }} |
Este es uno de los detalles más importantes del flujo de trabajo. La plantilla del repositorio no asume que el token siempre pertenezca a g-recaptcha-response. En este ejemplo, va en un encabezado personalizado.
price y productNameEl nodo HTML extrae:
| Clave | Selector CSS |
|---|---|
price |
.product-price, [data-price], .price |
productName |
h1, .product-title |
El nodo Code almacena y compara valores usando:
$workflow.staticData.lastPrice$workflow.staticData.lastCheckedEsto permite que el flujo de trabajo distinga entre:
El nodo IF comprueba {{ $json.changed }}.
Si el precio cambió, el flujo de trabajo va a Build Alert.
Si no, va a No Change.
En el camino de webhook, cualquiera de las ramas luego entra en Respond to Webhook.
Aunque el ejemplo principal incluye lógica de comparación de precios, es más útil pensar en él como una plantilla de scraper para páginas de productos protegidas con lógica de comparación.
Las partes reutilizables son:
Es por eso que la misma estructura puede impulsar:
Esta es la parte que importa más en un objetivo real.
Para la mayoría de los sitios reales, deberías asumir que casi todo aquí es ajustable: el tipo de desafío, los parámetros de resolución, dónde se envía el token, el cuerpo de la solicitud, las cookies, los encabezados, los selectores y hasta los criterios de éxito final. Estos flujos de trabajo del repositorio son ejemplos de patrones funcionales, no recetas fijas que se ajusten a cada sitio sin cambios.
Los flujos de uso del repositorio ahora soportan programación + webhook.
Usa:
Los caminos de webhook en estas plantillas son activadores de objetivos fijos, no APIs públicas para objetivos proporcionados por usuarios.
El ejemplo principal de monitoreo de precios usa reCAPTCHA v3, pero tu objetivo puede usar:
Si esto cambia, deberás actualizar el paso de resolución en consecuencia.
Incluso cuando dos sitios usan reCAPTCHA, las configuraciones aún pueden diferir.
Es posible que debas cambiar:
websiteURLwebsiteKeypageActionLa plantilla de scraper expone estos como campos de configuración de marcador de posición porque se espera que cambien.
No asumas que el token siempre va al mismo lugar.
Este repositorio ya muestra varios patrones:
| Patrón | Ejemplo del repositorio |
|---|---|
| Encabezado de solicitud | Scraping — CapSolver + Schedule usa x-recaptcha-token |
| Cuerpo del formulario | Los flujos de inicio de sesión suelen usar g-recaptcha-response en un cuerpo codificado como formulario |
En sitios reales, el token resuelto puede pertenecer a:
Este ejemplo del repositorio es un patrón de envío, no uno universal.
La solicitud protegida puede requerir más que solo el token de captcha o desafío.
Es posible que debas ajustar:
Eso es especialmente común para:
La plantilla principal de scraper extrae:
priceproductNamePero puedes reemplazarlo por:
El código de monitoreo de precios actual compara valores numéricos, pero el mismo patrón se puede adaptar para:
El JSON a continuación es la versión importable actual de Scraping — Price & Product Details — CapSolver + Schedule + Webhook de este repositorio, incluyendo los caminos de programación + webhook.
{
"nodes": [
{
"parameters": {
"content": "## Scraping \u2014 Price & Product Monitor\n\n### How it works\n\n1. Triggers either by schedule or webhook input to start price monitoring.\n2. Solves reCAPTCHA to access the targeted product page.\n3. Retrieves and extracts data from the product page for further analysis.\n4. Compares newly fetched data with previously stored data to detect changes.\n5. Determines if changes occurred and prepares alerts if needed.\n6. Sends responses based on data analysis through designated channels.\n\n### Setup steps\n\n- [ ] Configure scheduled trigger interval in 'Every 6 Hours' node.\n- [ ] Set target website details in 'Set Target Config [Schedule]'.\n- [ ] Configure reCAPTCHA solver with API key in 'Solve reCAPTCHA v3' nodes.\n- [ ] Set up Webhook URL and path in 'Webhook Trigger'.\n- [ ] Define alert criteria and destination in 'Build Alert' nodes.\n\n### Customization\n\nAdjust the extraction pattern in 'Extract Data' nodes to fit specific product details.",
"height": 896,
"width": 480
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1328,
-304
],
"id": "52c7808e-d2bc-4779-85e6-909a51066338",
"name": "Sticky Note"
},
{
"parameters": {
"content": "## Scheduled trigger setup\n\nInitializes the data monitoring process every 6 hours using a schedule trigger and sets the target configuration for scraping.",
"height": 320,
"width": 496,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-752,
-160
],
"id": "3c5cee67-552d-48ea-8717-7c5126269e2e",
"name": "Sticky Note1"
},
{
"parameters": {
"content": "## Proceso de raspado programado\n\nResuelve reCAPTCHA, obtiene la página del producto, extrae los datos y los compara con los registros anteriores para identificar cambios, siguiendo un disparador programado.",
"height": 496,
"width": 1680,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-144,
-304
],
"id": "d0315be2-111c-4893-bf42-2f2cc2eb186f",
"name": "Nota adhesiva2"
},
{
"parameters": {
"content": "## Configuración del disparador de webhook\n\nManeja la supervisión de datos activada manualmente a través de un webhook entrante y resuelve reCAPTCHA para continuar.",
"height": 304,
"width": 816,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-768,
336
],
"id": "a78f1606-07fb-40fd-af82-e1dc9b766206",
"name": "Nota adhesiva3"
},
{
"parameters": {
"content": "## Proceso de raspado mediante webhook\n\nProcesa las solicitudes activadas por webhook obteniendo la página del producto, extrayendo los datos y determinando los cambios.",
"height": 272,
"width": 1088,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
160,
320
],
"id": "1a677fd9-a3a8-404f-ba9a-2b087d7bfe11",
"name": "Nota adhesiva4"
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 6
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.3,
"position": [
-704,
0
],
"id": "sc-901",
"name": "Cada 6 horas"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "cfg-001",
"name": "websiteURL",
"value": "https://TU-SITIO-OBJETIVO.com/pagina-del-producto",
"type": "string"
},
{
"id": "cfg-002",
"name": "websiteKey",
"value": "TU-CLAVE-DE-SITIO-AQUÍ",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-400,
0
],
"id": "sc-900",
"name": "Establecer Configuración de destino [Programado]"
},
{
"parameters": {
"operation": "reCAPTCHA v3",
"websiteURL": "={{ $json.websiteURL }}",
"websiteKey": "={{ $json.websiteKey }}",
"optional": {
"pageAction": "ver_producto"
}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
-96,
0
],
"id": "sc-902",
"name": "Resolver reCAPTCHA v3",
"credentials": {
"capSolverApi": {
"id": "BeBFMAsySMsMGeE9",
"name": "Cuenta de CapSolver"
}
}
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Establecer Configuración de destino [Programado]').first().json.websiteURL }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "user-agent",
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
},
{
"name": "x-recaptcha-token",
"value": "={{ $json.data.solution.gRecaptchaResponse }}"
}
]
},
"options": {
"response": {
"response": {}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
208,
0
],
"id": "sc-903",
"name": "Obtener Página del Producto"
},
{
"parameters": {
"operation": "extraerContenidoHtml",
"extractionValues": {
"values": [
{
"key": "price",
"cssSelector": ".producto-precio, [data-precio], .precio"
},
{
"key": "productName",
"cssSelector": "h1, .titulo-del-producto"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.html",
"typeVersion": 1.2,
"position": [
512,
0
],
"id": "sc-904",
"name": "Extraer Datos"
},
{
"parameters": {
"jsCode": "const datosEstaticos = $workflow.staticData;\nconst precioActual = $input.first().json.price;\nconst precioAnterior = datosEstaticos.ultimoPrecio;\nconst nombreProducto = $input.first().json.productName || 'Producto';\nconst parsearPrecio = (cadena) => { if (!cadena) return null; const coincidencia = cadena.match(/[\\d,]+\\.?\\d*/); return coincidencia ? parseFloat(coincidencia[0].replace(',', '')) : null; };\nconst precioNumericoActual = parsearPrecio(precioActual);\nconst precioNumericoAnterior = parsearPrecio(precioAnterior);\ndatosEstaticos.ultimoPrecio = precioActual;\ndatosEstaticos.fechaUltimaVerificacion = new Date().toISOString();\nconst cambio = precioNumericoAnterior !== null && precioNumericoActual !== null && precioNumericoActual !== precioNumericoAnterior;\nconst direccion = cambio ? (precioNumericoActual < precioNumericoAnterior ? 'disminuyó' : 'aumentó') : 'sin cambios';\nconst diferencia = cambio ? Math.abs(precioNumericoActual - precioNumericoAnterior).toFixed(2) : '0';\nreturn [{ json: { nombreProducto, precioActual, precioAnterior: precioAnterior || 'primera verificación', cambio, direccion, diferencia: cambio ? `$${diferencia}` : null, fechaVerificacion: new Date().toISOString() } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
800,
0
],
"id": "sc-905",
"name": "Comparar Datos"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "si-1",
"leftValue": "={{ $json.cambio }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "y"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
1104,
0
],
"id": "sc-906",
"name": "¿Datos modificados?"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "a1",
"name": "alerta",
"value": "=Precio {{ $json.direccion }} para {{ $json.nombreProducto }}: {{ $json.precioAnterior }} \u2192 {{ $json.precioActual }}",
"type": "string"
},
{
"id": "a2",
"name": "severidad",
"value": "={{ $json.direccion === 'disminuyó' ? 'oferta' : 'información' }}",
"type": "string"
},
{
"id": "a3",
"name": "fechaVerificacion",
"value": "={{ $json.fechaVerificacion }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1392,
-192
],
"id": "sc-907",
"name": "Crear Alerta"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "n1",
"name": "estado",
"value": "sin_cambio",
"type": "string"
},
{
"id": "n2",
"name": "precioActual",
"value": "={{ $json.precioActual }}",
"type": "string"
},
{
"id": "n3",
"name": "fechaVerificacion",
"value": "={{ $json.fechaVerificacion }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1392,
32
],
"id": "sc-908",
"name": "Sin Cambio"
},
{
"parameters": {
"httpMethod": "POST",
"path": "monitoreo-de-precios",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-720,
464
],
"id": "sc-909",
"name": "Disparador de Webhook",
"webhookId": "sc-909-webhook",
"onError": "continuarSalidaRegular"
},
{
"parameters": {
"operation": "reCAPTCHA v3",
"websiteURL": "={{ $json.body.websiteURL }}",
"websiteKey": "={{ $json.body.websiteKey }}",
"optional": {
"pageAction": "={{ $json.body.pageAction || 'ver_producto' }}"
}
},
"type": "n8n-nodes-capsolver.capSolver",
"typeVersion": 1,
"position": [
-96,
464
],
"id": "sc-910",
"name": "Resolver reCAPTCHA v3 [Webhook]",
"credentials": {
"capSolverApi": {
"id": "BeBFMAsySMsMGeE9",
"name": "Cuenta de CapSolver"
}
}
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Disparador de Webhook').item.json.body.websiteURL }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "user-agent",
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
},
{
"name": "x-recaptcha-token",
"value": "={{ $json.data.solution.gRecaptchaResponse }}"
}
]
},
"options": {
"response": {
"response": {}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
208,
432
],
"id": "sc-911",
"name": "Obtener Página del Producto [Webhook]"
},
{
"parameters": {
"operation": "extraerContenidoHtml",
"extractionValues": {
"values": [
{
"key": "price",
"cssSelector": ".producto-precio, [data-precio], .precio"
},
{
"key": "productName",
"cssSelector": "h1, .titulo-del-producto"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.html",
"typeVersion": 1.2,
"position": [
512,
432
],
"id": "sc-912",
"name": "Extraer Datos [Webhook]"
},
{
"parameters": {
"jsCode": "const datosEstaticos = $workflow.staticData;\nconst precioActual = $input.first().json.price;\nconst precioAnterior = datosEstaticos.ultimoPrecio;\nconst nombreProducto = $input.first().json.productName || 'Producto';\nconst parsearPrecio = (cadena) => { if (!cadena) return null; const coincidencia = cadena.match(/[\\d,]+\\.?\\d*/); return coincidencia ? parseFloat(coincidencia[0].replace(',', '')) : null; };\nconst precioNumericoActual = parsearPrecio(precioActual);\nconst precioNumericoAnterior = parsearPrecio(precioAnterior);\ndatosEstaticos.ultimoPrecio = precioActual;\ndatosEstaticos.fechaUltimaVerificacion = new Date().toISOString();\nconst cambio = precioNumericoAnterior !== null && precioNumericoActual !== null && precioNumericoActual !== precioNumericoAnterior;\nconst direccion = cambio ? (precioNumericoActual < precioNumericoAnterior ? 'disminuyó' : 'aumentó') : 'sin cambios';\nconst diferencia = cambio ? Math.abs(precioNumericoActual - precioNumericoAnterior).toFixed(2) : '0';\nreturn [{ json: { nombreProducto, precioActual, precioAnterior: precioAnterior || 'primera verificación', cambio, direccion, diferencia: cambio ? `$${diferencia}` : null, fechaVerificacion: new Date().toISOString() } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
800,
432
],
"id": "sc-913",
"name": "Comparar Datos [Webhook]"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "si-2",
"leftValue": "={{ $json.cambio }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "y"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
1104,
432
],
"id": "sc-914",
"name": "¿Datos modificados? [Webhook]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "a4",
"name": "alerta",
"value": "=Precio {{ $json.direccion }} para {{ $json.nombreProducto }}: {{ $json.precioAnterior }} \u2192 {{ $json.precioActual }}",
"type": "string"
},
{
"id": "a5",
"name": "severidad",
"value": "={{ $json.direccion === 'disminuyó' ? 'oferta' : 'información' }}",
"type": "string"
},
{
"id": "a6",
"name": "fechaVerificacion",
"value": "={{ $json.fechaVerificacion }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1424,
384
],
"id": "sc-915",
"name": "Crear Alerta [Webhook]"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "n4",
"name": "estado",
"value": "sin_cambio",
"type": "string"
},
{
"id": "n5",
"name": "precioActual",
"value": "={{ $json.precioActual }}",
"type": "string"
},
{
"id": "n6",
"name": "fechaVerificacion",
"value": "={{ $json.fechaVerificacion }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1440,
592
],
"id": "sc-916",
"name": "Sin Cambio [Webhook]"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
1712,
512
],
"id": "sc-917",
"name": "Responder al Webhook"
}
],
"connections": {
"Cada 6 horas": {
"main": [
[
{
"node": "Configurar objetivo [Programar]",
"type": "principal",
"index": 0
}
]
]
},
"Configurar objetivo [Programar]": {
"principal": [
[
{
"node": "Resolver reCAPTCHA v3",
"type": "principal",
"index": 0
}
]
]
},
"Resolver reCAPTCHA v3": {
"principal": [
[
{
"node": "Obtener página del producto",
"type": "principal",
"index": 0
}
]
]
},
"Obtener página del producto": {
"principal": [
[
{
"node": "Extraer datos",
"type": "principal",
"index": 0
}
]
]
},
"Extraer datos": {
"principal": [
[
{
"node": "Comparar datos",
"type": "principal",
"index": 0
}
]
]
},
"Comparar datos": {
"principal": [
[
{
"node": "¿Datos cambiados?",
"type": "principal",
"index": 0
}
]
]
},
"¿Datos cambiados?": {
"principal": [
[
{
"node": "Crear alerta",
"type": "principal",
"index": 0
}
],
[
{
"node": "Sin cambios",
"type": "principal",
"index": 0
}
]
]
},
"Disparador de webhook": {
"principal": [
[
{
"node": "Resolver reCAPTCHA v3 [Webhook]",
"type": "principal",
"index": 0
}
]
]
},
"Resolver reCAPTCHA v3 [Webhook]": {
"principal": [
[
{
"node": "Obtener página del producto [Webhook]",
"type": "principal",
"index": 0
}
]
]
},
"Obtener página del producto [Webhook]": {
"principal": [
[
{
"node": "Extraer datos [Webhook]",
"type": "principal",
"index": 0
}
]
]
},
"Extraer datos [Webhook]": {
"principal": [
[
{
"node": "Comparar datos [Webhook]",
"type": "principal",
"index": 0
}
]
]
},
"Comparar datos [Webhook]": {
"principal": [
[
{
"node": "¿Datos cambiados? [Webhook]",
"type": "principal",
"index": 0
}
]
]
},
"¿Datos cambiados? [Webhook]": {
"principal": [
[
{
"node": "Crear alerta [Webhook]",
"type": "principal",
"index": 0
}
],
[
{
"node": "Sin cambios [Webhook]",
"type": "principal",
"index": 0
}
]
]
},
"Crear alerta [Webhook]": {
"principal": [
[
{
"node": "Responder al webhook",
"type": "principal",
"index": 0
}
]
]
},
"Sin cambios [Webhook]": {
"principal": [
[
{
"node": "Responder al webhook",
"type": "principal",
"index": 0
}
]
]
}
},
"pinData": {},
"meta": {
"instanceId": "962ff0267b713be0344b866fa54daae28de8ed2144e2e6867da355dae193ea1f"
}
}
``
</details>
---
## Prueba esto
Una vez que haya configurado los marcadores de posición y activado el flujo de trabajo, active la ruta del webhook:
```bash
curl -X POST https://your-n8n-instance.com/webhook/price-monitor \
-H "Content-Type: application/json" \
-d '{}'
Respuesta esperada (primera verificación):
{
"status": "no_change",
"currentPrice": "$29.99",
"checkedAt": "2026-03-11T08:00:00.000Z"
}
Respuesta esperada (precio cambiado):
{
"alert": "El precio ha bajado para Widget Pro: $39.99 → $29.99 (-$10.00)",
"severity": "deal",
"checkedAt": "2026-03-11T14:00:00.000Z"
}
Una respuesta con datos de precio reales confirma que todo el pipeline funcionó — captcha resuelto, página protegida obtenida, datos extraídos y lógica de comparación ejecutada.
Si CapSolver devuelve un token pero el sitio sigue bloqueando la solicitud, el problema suele no ser la resolución en sí. Causas comunes:
pageActionSi el objetivo utiliza un desafío no reCAPTCHA — como Cloudflare Turnstile, Cloudflare Challenge, GeeTest, DataDome, AWS WAF o MTCaptcha — el ejemplo principal no funcionará sin cambios. Debe actualizar:
Si el nodo HTML no extrae los campos que espera:
Las plantillas del repositorio se importan como inactivas. Hasta que:
la ruta del webhook no estará activa.
Crear alerta o los nodos de éxito/fallo de autenticación.¿Listo para comenzar? Regístrese en CapSolver y use el código de bonificación OPENCLAW para obtener un 6% adicional en su primer recarga!
La lección principal es simple: resolver captchas es solo un paso en el flujo de trabajo. El raspador real aún debe enviar el token correctamente, enviar la forma de solicitud adecuada y extraer los campos que importan para su caso de uso.
Eso también es por qué estas plantillas deben tratarse como ejemplos. Un sitio diferente puede utilizar un tipo de captcha diferente, esperar el token en otro lugar, necesitar cookies o campos adicionales, devolver una forma de respuesta diferente y requerir lógica de extracción o validación diferente.
Esta plantilla le da un punto de partida para:
Utiliza el patrón general:
disparador -> resolver captchas -> enviar solicitud protegida -> extraer o verificar resultado -> salida
Configure los marcadores de posición, mantenga los flujos inactivos hasta que coincidan con su objetivo y luego active la ruta de programación o webhook que se adapte a su caso de uso.
La plantilla de raspador se puede adaptar para flujos de inicio de sesión cambiando el nodo HTTP Request para enviar credenciales junto con el token resuelto. Consulte las guías dedicadas a tipos de captcha (reCAPTCHA, Turnstile, etc.) para plantillas de flujo de trabajo de inicio de sesión listas.
Entonces debe modificar el flujo de trabajo. Las configuraciones de reCAPTCHA y el patrón de solicitud del ejemplo principal no son universales. CapSolver admite Cloudflare Turnstile, Cloudflare Challenge, GeeTest V3/V4, DataDome, AWS WAF, MTCaptcha y otros. Actualice el paso de resolución de CapSolver y la solicitud protegida para que coincidan con el tipo de desafío real y el patrón de envío de token utilizado por el objetivo.
Donde el sitio objetivo lo espera. Podría ser:
La plantilla de monitoreo de precios utiliza un encabezado. Otros sitios variarán.
Normalmente, sí. Incluso los sitios que utilizan la misma familia de captchas pueden requerir diferentes websiteURL, websiteKey, pageAction, configuraciones invisibles u otras opciones de tarea.
Sí. Cambie los selectores y la lógica de salida según lo que necesite, como existencias, título, SKU, descripción, contenido protegido, estado de inicio de sesión o señales de salud del sitio.
Comience verificando la respuesta protegida devuelta por el nodo HTTP Request.
Depure el flujo de trabajo en ese orden: resolver -> enviar -> inspeccionar respuesta -> extraer.
Crea una API para resolver reCAPTCHA v2/v3 utilizando CapSolver y n8n. Aprende a automatizar la obtención de tokens, enviarlos a los sitios web y extraer datos protegidos sin necesidad de programar.

Descubre la mejor inteligencia artificial para resolver acertijos de imágenes. Aprende cómo el Motor de Visión de CapSolver y las APIs ImageToText automatizan desafíos visuales complejos con alta precisión.
