{"_id":"@agustinespildora/open-banking-chile","_rev":"2-910fb072e46792611a30de0195ba3f04","name":"@agustinespildora/open-banking-chile","dist-tags":{"latest":"2.0.2"},"versions":{"2.0.1":{"name":"@agustinespildora/open-banking-chile","version":"2.0.1","keywords":["open-banking","chile","bank-scraper","finanzas","banking","scraper","puppeteer","banco-falabella","banco-chile","santander","bci","banco-estado","movimientos","cartola"],"author":{"name":"Kai Horwitz","email":"kai@makana.cl"},"license":"MIT","_id":"@agustinespildora/open-banking-chile@2.0.1","maintainers":[{"name":"agustinespildora","email":"agustinespildora@gmail.com"}],"homepage":"https://github.com/agustinespildora/open-banking-chile#readme","bugs":{"url":"https://github.com/agustinespildora/open-banking-chile/issues"},"bin":{"open-banking-chile":"dist/cli.js"},"dist":{"shasum":"9f2fd57cf90719f81ea11d2ac0928b883ee7aa00","tarball":"https://registry.npmjs.org/@agustinespildora/open-banking-chile/-/open-banking-chile-2.0.1.tgz","fileCount":11,"integrity":"sha512-1PRMDOl2SmWh7UfyIRZdwaGI35Js09XMnX28iffAnPBBnhEtb7pztaCX60PrJX7rj1ik0C1eaNELE15ewY/NyA==","signatures":[{"sig":"MEQCIFzQ0p9761/y1aNlYE/9tbdsuRdaoKixq/Idtwr2F0RPAiAZsKhd+BzuekMOJPyZjLYQULMR4RTeG5kGX7dZ9+y/FA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1052150},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","engines":{"node":">=22.12.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"1522927f4178c76193a2cb8934c618f58fd1bbb7","scripts":{"dev":"tsup --watch","test":"vitest run --exclude test/cartola-date.test.mjs && npm run test:cartola-date","build":"tsup","start":"node dist/cli.js","prepack":"npm run build","test:watch":"vitest","test:cartola-date":"npm run build && node test/cartola-date.test.mjs"},"_npmUser":{"name":"agustinespildora","email":"agustinespildora@gmail.com"},"repository":{"url":"git+https://github.com/agustinespildora/open-banking-chile.git","type":"git"},"_npmVersion":"10.9.4","description":"Scrapers open source para bancos chilenos. Obtén tus movimientos y saldo como JSON. Open source scrapers for Chilean banks.","directories":{},"_nodeVersion":"22.22.0","dependencies":{"dotenv":"^17.3.1","puppeteer-core":"^25.9.0","playwright-core":"^1.59.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^3.2.4","typescript":"^5.9.3","@types/node":"^20"},"_npmOperationalInternal":{"tmp":"tmp/open-banking-chile_2.0.1_1787777848852_0.24686632380760964","host":"s3://npm-registry-packages-npm-production"}},"2.0.2":{"name":"@agustinespildora/open-banking-chile","version":"2.0.2","description":"Scrapers open source para bancos chilenos. Obtén tus movimientos y saldo como JSON. Open source scrapers for Chilean banks.","type":"module","main":"dist/index.cjs","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"bin":{"open-banking-chile":"dist/cli.js"},"scripts":{"build":"tsup","dev":"tsup --watch","start":"node dist/cli.js","test":"vitest run --exclude test/cartola-date.test.mjs && npm run test:cartola-date","test:watch":"vitest","prepack":"npm run build","test:cartola-date":"npm run build && node test/cartola-date.test.mjs"},"keywords":["open-banking","chile","bank-scraper","finanzas","banking","scraper","puppeteer","banco-falabella","banco-chile","santander","bci","banco-estado","movimientos","cartola"],"author":{"name":"Kai Horwitz","email":"kai@makana.cl"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/agustinespildora/open-banking-chile.git"},"engines":{"node":">=22.12.0"},"dependencies":{"dotenv":"^17.3.1","playwright-core":"^1.59.1","puppeteer-core":"^25.9.0"},"devDependencies":{"@types/node":"^20","tsup":"^8.5.1","typescript":"^5.9.3","vitest":"^3.2.4"},"publishConfig":{"access":"public"},"_id":"@agustinespildora/open-banking-chile@2.0.2","gitHead":"8ce66ade1340096a0799535f6da6c0dd0911ce09","bugs":{"url":"https://github.com/agustinespildora/open-banking-chile/issues"},"homepage":"https://github.com/agustinespildora/open-banking-chile#readme","_nodeVersion":"22.22.0","_npmVersion":"10.9.4","dist":{"integrity":"sha512-TjEce30dYyLXOdJdhdPUQ945yyjHRpmU8EqLqv474sGnCAABXFWDNDKvbNUnICZIfnwzfPbanEchZBEBCgVg/g==","shasum":"a244c5f4493797e1500145afd93c11ac5d23429c","tarball":"https://registry.npmjs.org/@agustinespildora/open-banking-chile/-/open-banking-chile-2.0.2.tgz","fileCount":11,"unpackedSize":1057895,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCiVjVlq9PNAXC3JXC8DkIYqB/vQzIfV6vA3s5DVyiiHgIhANkeqD1payjXUi7lp/i7zTVJIaW/TpKsR8pbasNYJH7L"}]},"_npmUser":{"name":"agustinespildora","email":"agustinespildora@gmail.com"},"directories":{},"maintainers":[{"name":"agustinespildora","email":"agustinespildora@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/open-banking-chile_2.0.2_1787847815951_0.7077058753502428"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-26T20:57:28.592Z","modified":"2026-08-27T16:23:36.331Z","2.0.1":"2026-08-26T20:57:29.042Z","2.0.2":"2026-08-27T16:23:36.176Z"},"bugs":{"url":"https://github.com/agustinespildora/open-banking-chile/issues"},"author":{"name":"Kai Horwitz","email":"kai@makana.cl"},"license":"MIT","homepage":"https://github.com/agustinespildora/open-banking-chile#readme","keywords":["open-banking","chile","bank-scraper","finanzas","banking","scraper","puppeteer","banco-falabella","banco-chile","santander","bci","banco-estado","movimientos","cartola"],"repository":{"type":"git","url":"git+https://github.com/agustinespildora/open-banking-chile.git"},"description":"Scrapers open source para bancos chilenos. Obtén tus movimientos y saldo como JSON. Open source scrapers for Chilean banks.","maintainers":[{"name":"agustinespildora","email":"agustinespildora@gmail.com"}],"readme":"# Open Banking Chile\n\nScrapers open source para bancos chilenos. Obtén tus movimientos bancarios y saldo como JSON limpio.\n\n> **Disclaimer**: Este proyecto no está afiliado con ningún banco. Úsalo bajo tu propia responsabilidad y solo con tus propias credenciales.\n\n## Migración v2 → v3\n\n**v3.0.0 introduce un cambio breaking en `ScrapeResult`:**\n\nLos movimientos ya no están en un array plano `result.movements` — ahora viven dentro de cada cuenta/tarjeta:\n\n| Antes (v2)               | Ahora (v3)                                  |\n| ------------------------ | ------------------------------------------- |\n| `result.movements`       | `result.accounts[i].movements`              |\n| `result.balance`         | `result.accounts[i].balance`                |\n| _(no existía)_           | `result.creditCards[i].movements`           |\n\n```ts\n// v2 (ya no válido)\nconsole.log(result.balance);\nfor (const m of result.movements) { ... }\n\n// v3\nconst cuenta = result.accounts?.[0];\nconsole.log(cuenta?.balance);\nfor (const m of cuenta?.movements ?? []) { ... }\n\n// Movimientos de una tarjeta específica\nfor (const card of result.creditCards ?? []) {\n  console.log(card.label, card.movements?.length);\n}\n```\n\nLos campos `movements` y `balance` en `ScrapeResult` se mantienen como `@deprecated` para compatibilidad temporal.\n\n## Migración v1 → v2\n\n**v2.0.0 introduce un cambio breaking en la interfaz `BankMovement`:**\n\nEl campo `source` ahora es **obligatorio** e indica el origen del movimiento. Si construyes objetos `BankMovement` manualmente, agrega `source: \"account\"`. Si solo consumes resultados del scraper, no hay cambios necesarios.\n\nTambién en esta versión: utilidades compartidas (`parseChileanAmount`, `normalizeDate`, `deduplicateMovements`, etc.) disponibles como exports desde `open-banking-chile/utils`.\n\n## Bancos soportados\n\n| Banco                             | ID           | Estado       |\n| --------------------------------- | ------------ | ------------ |\n| Banco Falabella (cuenta + CMR TC) | `falabella`  | ✅ Funcional |\n| Banco BICE                        | `bice`       | ✅ Funcional |\n| Banco Santander                   | `santander`  | ✅ Funcional |\n| Banco Edwards                     | `edwards`    | ✅ Funcional |\n| Scotiabank                        | `scotiabank` | ✅ Funcional |\n| Banco de Chile                    | `bchile`     | ✅ Funcional |\n| BCI                               | `bci`        | ✅ Funcional |\n| Itaú                              | `itau`       | ✅ Funcional |\n| Banco Estado (CuentaRUT)          | `bestado`    | ✅ Funcional |\n| Tarjeta Cencosud                  | `cencosud`   | ✅ Funcional |\n\n**¿Tu banco no está?** → [Contribuir](#contribuir)\n\n## Requisitos\n\n- **Node.js** >= 18\n- **Google Chrome** o **Chromium**\n\n```bash\n# Instalar Chrome — Ubuntu/Debian\nsudo apt update && sudo apt install -y google-chrome-stable\n\n# macOS\nbrew install --cask google-chrome\n```\n\n## Instalación\n\n```bash\n# Desde GitHub\nnpm install github:kaihv/open-banking-chile\n\n# O clonar el repo\ngit clone https://github.com/kaihv/open-banking-chile.git\ncd open-banking-chile\nnpm install\nnpm run build\n```\n\n## Uso\n\n### CLI\n\nConfigura tu archivo `.env` con tus credenciales:\n\n```bash\n# Banco Falabella\nFALABELLA_RUT=12345678-9\nFALABELLA_PASS=tu_clave\n\n# Banco BICE\nBICE_RUT=12345678-9\nBICE_PASS=tu_clave\n## Opcional:\nBICE_MONTHS=1\n\n# Banco Santander\nSANTANDER_RUT=12345678-9\nSANTANDER_PASS=tu_clave\n\n# Banco de Chile\nBANCOCHILE_RUT=12345678-9\nBANCOCHILE_PASS=tu_clave\n\n# Banco Edwards\nEDWARDS_RUT=12345678-9\nEDWARDS_PASS=tu_clave\n\n\n# Itaú\nITAU_RUT=12345678-9\nITAU_PASS=tu_clave\n\n# Banco Estado\nBESTADO_RUT=12345678-9\nBESTADO_PASS=tu_clave\n\n# Tarjeta Cencosud\nCENCOSUD_RUT=12345678-9\nCENCOSUD_PASS=tu_clave\n```\n\nEjecuta la librería con el comando `npx`, `dotenv` incluirá automáticamente las variables de entorno.\n\n```bash\n\n# Consultar banco\nnpx open-banking-chile --bank falabella --pretty\nnpx open-banking-chile --bank santander --pretty\nnpx open-banking-chile --bank bchile --pretty\nnpx open-banking-chile --bank edwards --pretty\nnpx open-banking-chile --bank itau --pretty\nnpx open-banking-chile --bank bestado --pretty\nnpx open-banking-chile --bank cencosud --pretty\n\n# Solo movimientos\nnpx open-banking-chile --bank falabella --movements | jq .\n\n# Listar bancos disponibles\nnpx open-banking-chile --list\n\n# Con screenshots para debugging\nnpx open-banking-chile --bank falabella --screenshots --pretty\n```\n\n**Opciones CLI:**\n\n| Flag                | Descripción                                                     |\n| ------------------- | --------------------------------------------------------------- |\n| `--bank <id>`       | Banco a consultar (requerido)                                   |\n| `--list`            | Listar bancos disponibles                                       |\n| `--pretty`          | JSON formateado                                                 |\n| `--movements`       | Solo array de movimientos                                       |\n| `--screenshots`     | Guardar screenshots locales en `./screenshots/`                 |\n| `--headful`         | Chrome visible (debugging). **BancoEstado siempre usa headful** |\n| `--owner <T\\|A\\|B>` | Filtro Titular/Adicional para TC (default: B = todos)           |\n| `--statement-months <N>` | Estados de cuenta de TC a leer, del más reciente hacia atrás (default: 1). Solo Banco de Chile |\n\n### Como librería\n\n```typescript\nimport { banks, getBank } from \"open-banking-chile\";\n\n// Opción 1: por ID\nconst falabella = getBank(\"falabella\");\nconst result = await falabella!.scrape({\n  rut: \"12345678-9\",\n  password: \"mi_clave\",\n});\n\n// Opción 2: import directo\nimport { falabella } from \"open-banking-chile\";\nconst result = await falabella.scrape({\n  rut: \"12345678-9\",\n  password: \"mi_clave\",\n});\n\nif (result.success) {\n  console.log(`Banco: ${result.bank}`);\n\n  // Cuenta corriente\n  for (const account of result.accounts ?? []) {\n    console.log(`Saldo: $${account.balance?.toLocaleString(\"es-CL\")}`);\n    for (const m of account.movements) {\n      const sign = m.amount > 0 ? \"+\" : \"\";\n      console.log(`${m.date} | ${m.description.padEnd(40)} | ${sign}$${m.amount.toLocaleString(\"es-CL\")}`);\n    }\n  }\n\n  // Tarjetas de crédito\n  for (const card of result.creditCards ?? []) {\n    console.log(`\\nTarjeta: ${card.label}`);\n    for (const m of card.movements ?? []) {\n      const sign = m.amount > 0 ? \"+\" : \"\";\n      console.log(`${m.date} | ${m.description.padEnd(40)} | ${sign}$${m.amount.toLocaleString(\"es-CL\")} [${m.source}]`);\n    }\n  }\n}\n```\n\n### Meses anteriores de tarjeta de crédito (`statementMonths`)\n\nUn movimiento de TC sale del feed de no facturados en cuanto se factura, y desde\nahí el banco solo lo expone dentro del estado de cuenta de su período. Por\ndefecto se lee un solo estado de cuenta, el más reciente, así que todo lo\nfacturado en períodos anteriores queda fuera. `statementMonths` decide cuántos\nleer, del más nuevo hacia atrás:\n\n```typescript\nconst result = await getBank(\"bchile\")!.scrape({\n  rut: \"12345678-9\",\n  password: \"mi_clave\",\n  statementMonths: 4,\n});\n```\n\nCada período agrega dos llamadas a la API del banco, sin login extra. La\nmetadata de la tarjeta (`nextBillingDate`, `nextDueDate`, `lastStatement`,\n`billingPeriod`) siempre sale del estado de cuenta más reciente. Hoy solo lo usa\nBanco de Chile.\n\n### Output\n\n```json\n{\n  \"success\": true,\n  \"bank\": \"falabella\",\n  \"accounts\": [\n    {\n      \"balance\": 1250000,\n      \"movements\": [\n        {\n          \"date\": \"08-03-2026\",\n          \"description\": \"COMPRA SUPERMERCADO LIDER\",\n          \"amount\": -45230,\n          \"balance\": 1250000,\n          \"source\": \"account\"\n        }\n      ]\n    }\n  ],\n  \"creditCards\": [\n    {\n      \"label\": \"CMR Mastercard ****1234\",\n      \"national\": { \"used\": 50000, \"available\": 950000, \"total\": 1000000 },\n      \"nextBillingDate\": \"19-04-2026\",\n      \"nextDueDate\": \"05-05-2026\",\n      \"periodExpenses\": 15990,\n      \"movements\": [\n        {\n          \"date\": \"07-03-2026\",\n          \"description\": \"COMPRA COMERCIO\",\n          \"amount\": -15990,\n          \"balance\": 0,\n          \"source\": \"credit_card_unbilled\",\n          \"card\": \"****1234\",\n          \"owner\": \"titular\",\n          \"installments\": \"01/03\",\n          \"totalAmount\": 47970\n        },\n        {\n          \"date\": \"01-03-2026\",\n          \"description\": \"PAGO TARJETA DE CRÉDITO\",\n          \"amount\": 70000,\n          \"balance\": 0,\n          \"source\": \"credit_card_billed\",\n          \"card\": \"****1234\"\n        }\n      ]\n    }\n  ]\n}\n```\n\n### Campo `source`\n\nCada movimiento incluye un campo `source` que indica su origen:\n\n| Valor                  | Descripción                       |\n| ---------------------- | --------------------------------- |\n| `account`              | Cuenta corriente o vista          |\n| `credit_card_unbilled` | Tarjeta de crédito — por facturar |\n| `credit_card_billed`   | Tarjeta de crédito — facturado    |\n\nCampos opcionales en `BankMovement`:\n\n| Campo          | Descripción                                                                 |\n| -------------- | --------------------------------------------------------------------------- |\n| `owner`        | `\"titular\"` o `\"adicional\"` (Falabella CMR)                                 |\n| `card`         | Máscara de la tarjeta, ej: `\"****8335\"` (BChile, Falabella)                 |\n| `installments` | Cuotas en formato `NN/NN`, ej: `\"02/06\"` = cuota 2 de 6                     |\n| `totalAmount`  | Monto total de la compra cuando es en cuotas (Falabella)                    |\n\n## Seguridad\n\n- **Tus credenciales nunca salen de tu máquina**. Todo corre 100% local.\n- No hay analytics, telemetría, ni tracking.\n- Las credenciales se pasan por env vars, nunca se guardan en disco.\n- Los screenshots de debug pueden contener datos sensibles — no los compartas.\n- Lee [SECURITY.md](SECURITY.md) para más detalles.\n\n## Arquitectura\n\nEl proyecto sigue una **arquitectura limpia en tres capas**, separando responsabilidades para facilitar la reutilización y la adición de nuevos bancos:\n\n```\nsrc/\n  index.ts                    — Registro de bancos, getBank(), listBanks()\n  types.ts                    — Interfaces: BankScraper, BankMovement, ScrapeResult\n  utils.ts                    — Utilidades compartidas (parsing, fechas, dedup)\n  cli.ts                      — CLI entry point\n  infrastructure/\n    browser.ts                — Gestión centralizada del browser (launch, sesión, cleanup)\n    scraper-runner.ts         — Pipeline de ejecución (credenciales → browser → scrape → logout → resultado)\n  actions/\n    login.ts                  — Login genérico (RUT, password, submit, detección de errores)\n    navigation.ts             — Navegación DOM (click por texto, sidebars, banners)\n    extraction.ts             — Extracción de movimientos desde tablas HTML\n    pagination.ts             — Iteración multi-página (Siguiente, Ver más)\n    credit-card.ts            — Extracción de movimientos de tarjeta de crédito\n    balance.ts                — Extracción de saldo\n    two-factor.ts             — Detección y espera de 2FA\n  banks/\n    falabella.ts              — Banco Falabella + CMR (cuenta + tarjeta de crédito)\n    bestado.ts                — Banco Estado (CuentaRUT, requiere headful)\n    bchile.ts                 — Banco de Chile\n    bci.ts                    — BCI (iframes + BCI Pass)\n    bice.ts                   — Banco BICE\n    cencosud.ts               — Tarjeta Cencosud (hCaptcha intermitente, requiere --headful si aparece)\n    edwards.ts                — Banco Edwards\n    itau.ts                   — Itaú\n    santander.ts              — Banco Santander\n    scotiabank.ts             — Scotiabank Chile\n```\n\n### Capas\n\n**Infrastructure** — Gestión del ciclo de vida del browser. `launchBrowser()` centraliza la configuración de Chrome (anti-detección, user agent, modo headful/headless). `runScraper()` envuelve toda la ejecución: valida credenciales, abre el browser, ejecuta el scraper del banco, hace logout y cierra el browser. Los errores se capturan y retornan como `ScrapeResult`.\n\n**Actions** — Operaciones reutilizables e independientes del banco. Cada banco compone estas acciones en vez de reimplementarlas. Por ejemplo, `fillRut()` soporta múltiples formatos de RUT y funciona tanto en `Page` como en iframes; `paginateAndExtract()` navega automáticamente por páginas acumulando movimientos; `detect2FA()` detecta segundo factor por keywords configurables.\n\n**Banks** — Orquestación específica de cada banco. Solo contienen la lógica particular: selectores CSS propios, flujo de navegación, y configuración de 2FA. Usan `runScraper()` como wrapper y componen acciones del layer anterior.\n\n### Utilidades compartidas (`utils.ts`)\n\nFunciones comunes usadas por scrapers y acciones:\n\n| Función                                         | Descripción                                                            |\n| ----------------------------------------------- | ---------------------------------------------------------------------- |\n| `parseChileanAmount(text)`                      | Parsea montos en formato chileno ($1.234.567) a número                 |\n| `normalizeDate(raw)`                            | Normaliza fechas a DD-MM-YYYY (soporta dd/mm/yyyy, \"9 mar 2026\", etc.) |\n| `normalizeOwner(raw)`                           | Normaliza owner a `\"titular\"` o `\"adicional\"`                          |\n| `normalizeInstallments(raw)`                    | Normaliza cuotas a formato NN/NN (ej: \"1/3\" → \"01/03\")                 |\n| `deduplicateMovements(movements)`               | Elimina movimientos duplicados por fecha+descripción+monto+source      |\n| `logout(page, debugLog)`                        | Cierra sesión buscando botones comunes (cerrar sesión, salir, etc.)    |\n| `formatRut(rut)`                                | Formatea RUT (12345678-9 → 12.345.678-9)                               |\n| `findChrome()`                                  | Busca Chrome/Chromium en el sistema                                    |\n| `closePopups(page)`                             | Cierra popups y modales genéricos                                      |\n| `delay(ms)`                                     | Espera N milisegundos                                                  |\n| `saveScreenshot(page, name, enabled, debugLog)` | Guarda screenshot si está habilitado                                   |\n\n## Contribuir\n\nQueremos cubrir **todos los bancos de Chile**. Si tienes cuenta en un banco que falta:\n\n1. Lee [CONTRIBUTING.md](CONTRIBUTING.md) para la guía paso a paso\n2. Crea `src/banks/<tu-banco>.ts` implementando `BankScraper`\n3. Usa `runScraper()` de `infrastructure/` y compone acciones de `actions/` (login, extracción, paginación, etc.)\n4. Usa las utilidades compartidas de `utils.ts` (parsing, fechas, dedup, logout)\n5. Regístralo en `src/index.ts`\n6. Abre un PR\n\n```typescript\n// La interfaz es simple:\ninterface BankScraper {\n  id: string; // \"mi-banco\"\n  name: string; // \"Mi Banco Chile\"\n  url: string; // \"https://www.mibanco.cl\"\n  scrape(options: ScraperOptions): Promise<ScrapeResult>;\n}\n```\n\n## Automatización (cron)\n\n```bash\n# Ejemplo: sincronizar Falabella diariamente a las 7 AM\n0 7 * * * source /home/user/.env && node /path/to/dist/cli.js --bank falabella >> /var/log/bank-sync.log 2>&1\n\n# Ejemplo: sincronizar BICE diariamente y con 3 meses históricos\n0 7 * * * source /home/user/.env && BICE_MONTHS=3 node /path/to/dist/cli.js --bank bice >> /var/log/bank-sync.log 2>&1\n```\n\n## Troubleshooting\n\n| Problema              | Solución                                                                                       |\n| --------------------- | ---------------------------------------------------------------------------------------------- |\n| Chrome no encontrado  | Instala Chrome o usa `CHROME_PATH=/ruta/chrome`                                                |\n| 2FA / Clave dinámica  | Si aparece, apruébalo manualmente en tu banco y vuelve a intentar                              |\n| 0 movimientos         | Usa `--screenshots --pretty` y revisa el debug log                                             |\n| Login falla           | Verifica RUT y clave, prueba con `--headful`                                                   |\n| BancoEstado bloqueado | BancoEstado bloquea headless (TLS fingerprinting). Siempre abre Chrome visible. Ver nota abajo |\n| Cencosud pide CAPTCHA | Ocurre ocasionalmente. En headless retorna error — reintenta con `--headful` para resolverlo manualmente |\n\n### BancoEstado y modo headless\n\nBancoEstado detecta navegadores headless a nivel de red (TLS fingerprinting), no solo por JavaScript. Ni `puppeteer-extra-plugin-stealth` ni `rebrowser-puppeteer-core` logran evadir esta detección. El scraper siempre corre en modo headful (Chrome visible).\n\n### Tarjeta Cencosud y CAPTCHA\n\nTarjeta Cencosud presenta ocasionalmente un hCaptcha en el login. No siempre aparece.\n\n- **Headless** (modo por defecto): el scraper detecta el CAPTCHA y retorna un error claro.\n- **Headful** (`--headful`): el scraper pausa y espera a que resuelvas el CAPTCHA manualmente en el navegador visible, luego continúa.\n\n```bash\nnode dist/cli.js --bank cencosud --headful --pretty\n```\n\nEl tiempo máximo de espera es 180 segundos (configurable con `CENCOSUD_CAPTCHA_TIMEOUT=segundos`).\n\n**En servidores Linux sin GUI**, usa Xvfb (display virtual):\n\n```bash\n# Instalar\nsudo apt install xvfb\n\n# Correr con display virtual\nxvfb-run node dist/cli.js --bank bestado --pretty\n\n# O como parte de tu app\nxvfb-run node tu-app.js\n```\n\n**En Docker:**\n\n```dockerfile\nRUN apt-get update && apt-get install -y xvfb google-chrome-stable\nCMD [\"xvfb-run\", \"node\", \"server.js\"]\n```\n\n**En Mac/Windows** no necesitas nada extra — Chrome se abre y cierra automáticamente.\n\n## License\n\nMIT — Hecho en Chile 🇨🇱\n","readmeFilename":"README.md"}