Scrape transactions from all 18 Israeli banks and credit card companies with built-in Cloudflare WAF bypass.
Maintained fork of eshaham/israeli-bank-scrapers, completely rewritten with Camoufox (Firefox anti-detect), Playwright, and TypeScript 5.9 strict mode.
npm install @sergienko4/israeli-bank-scrapers
Table of Contents
| Upstream | This Fork | |
|---|---|---|
| WAF bypass | No (Puppeteer blocked) | Yes (Camoufox, first attempt) |
| Login detection | Hardcoded CSS | 7-strategy auto-resolver |
| OTP | Manual | Auto-detect + fill |
| Module format | CJS only | Dual ESM + CJS |
| Tests | ~600 | 972 (95 suites) |
import { CompanyTypes, createScraper } from '@sergienko4/israeli-bank-scrapers';
const scraper = createScraper({
companyId: CompanyTypes.amex,
startDate: new Date('2024-01-01'),
});
const result = await scraper.scrape({
id: '123456789',
card6Digits: '123456',
password: 'mypassword',
});
if (result.success) {
for (const account of result.accounts!) {
console.log(`${account.accountNumber}: ${account.txns.length} transactions`);
}
} else {
console.error(result.errorType, result.errorMessage);
if (result.errorDetails) {
console.error('Suggestions:', result.errorDetails.suggestions);
}
}
| Institution | Type | Credentials |
|---|---|---|
| Bank Hapoalim | Bank | userCode, password |
| Bank Leumi | Bank | username, password |
| Discount Bank | Bank | id, password, num |
| Mercantile Bank | Bank | id, password, num |
| Mizrahi Tefahot | Bank | username, password |
| Otsar Hahayal | Bank | username, password |
| Beinleumi | Bank | username, password, OTP |
| Massad | Bank | username, password |
| Yahav | Bank | username, nationalID, password |
| Pagi | Bank | username, password |
| OneZero | Bank | email, password, OTP |
| Beyahad Bishvilha | Bank | id, password |
| Behatsdaa | Bank | id, password |
| Amex | Credit Card | id, card6Digits, password |
| Isracard | Credit Card | id, card6Digits, password |
| Visa Cal | Credit Card | username, password |
| Max | Credit Card | username, password, id (conditional) |
Browser banks (Beinleumi, Discount) — pass callback in options:
createScraper({
companyId: CompanyTypes.beinleumi, startDate,
otpCodeRetriever: async (phoneHint) => await getCodeFromUser(phoneHint),
});
API banks (OneZero) — pass callback in credentials:
await scraper.scrape({
email, password, phoneNumber: '+972...',
otpCodeRetriever: async () => '123456',
});
// result.persistentOtpToken — save to skip SMS next run
| Error | Meaning |
|---|---|
INVALID_PASSWORD |
Wrong credentials |
INVALID_OTP |
Wrong/expired OTP code |
WAF_BLOCKED |
Cloudflare block — check errorDetails.suggestions |
TIMEOUT |
Page load timeout — increase defaultTimeout |
TWO_FACTOR_RETRIEVER_MISSING |
OTP needed but no callback set |
Camoufox passes most challenges automatically. If you still get WAF_BLOCKED:
| Scenario | Fix |
|---|---|
| 403 after login | Wait 1-2 hours, reduce frequency |
| Datacenter IP blocked | Use residential proxy |
| Turnstile CAPTCHA | Run once headed to pass initial challenge |
| Parallel failures | Share browser, add 2-5s delay |
import { Camoufox } from '@hieutran094/camoufox-js';
const browser = await Camoufox({ headless: true });
const results = await Promise.all(
banks.map(async ({ companyId, credentials }) => {
const ctx = await browser.newContext();
const scraper = createScraper({ companyId, startDate, browserContext: ctx });
const result = await scraper.scrape(credentials);
await ctx.close();
return result;
}),
);
await browser.close();
createScraper({
companyId: CompanyTypes.leumi, startDate,
defaultTimeout: 60000,
navigationRetryCount: 2,
});
- npm install israeli-bank-scrapers
+ npm install @sergienko4/israeli-bank-scrapers
Same API. Both import and require() work. Types now use I prefix (IScraper, IScraperScrapingResult) — old names still work as aliases.
Login flow uses an 8-step middleware chain:
navigate > parse-page > fill > wait > check-result > [otp-confirm > otp-code] > post-action
Fields resolved by 7-strategy SelectorResolver (label text, textContent walk-up, placeholder, aria, name, CSS, xpath). After first field resolves, FormAnchor scopes subsequent fields to the discovered <form>.
All 18 institutions configured via declarative LoginConfig objects. Adding a new bank requires one config object.
| Version | Milestone |
|---|---|
| v6.7.2 | Initial fork from upstream |
| v7.0.0 | Puppeteer to Playwright |
| v7.9.0 | Camoufox anti-detect browser |
| v7.10.0 | Full ESM migration |
| v8.0.0 | Strict ESLint + JSDoc, I-prefix interfaces, form-anchor |
Thanks to the original israeli-bank-scrapers contributors whose work inspired this fork:
Sergienko Eugune 💻 📖 ⚠️ 🚧 🚇 |
Elad Shaham 💻 |
sebikaplun 💻 |
esakal 💻 |
ezzatq 💻 |
kfirarad 💻 |
baruchiro 💻 |
matanelgabsi 💻 |
dratler 💻 |
dudiventura 💻 |
gczobel 💻 |
orzarchi 💻 |
erezd 💻 |
erikash 💻 |
daniel-hauser 💻 |
MIT. Maintained by @sergienko4. Based on eshaham/israeli-bank-scrapers.