main.stealth.js: puppeteer-extra-plugin-stealth enough to avoid hcaptcha, claim successful

This commit is contained in:
Ralf Vogler 2021-12-28 00:51:21 +01:00
parent ba97a0e840
commit 64d0ba8ce7
4 changed files with 212 additions and 3 deletions

View file

@ -3,6 +3,7 @@ if (!existsSync('auth.json')) {
console.error('Missing auth.json! Run `npm login` to login and create this file by closing the opened browser.'); console.error('Missing auth.json! Run `npm login` to login and create this file by closing the opened browser.');
} }
// npm i playwright playwright-extra@next @extra/recaptcha@next
const { chromium } = require('playwright-extra') const { chromium } = require('playwright-extra')
// add recaptcha plugin and provide it your 2captcha token (= their apiKey) // add recaptcha plugin and provide it your 2captcha token (= their apiKey)

66
main.stealth.js Normal file
View file

@ -0,0 +1,66 @@
const { existsSync } = require('fs');
if (!existsSync('auth.json')) {
console.error('Missing auth.json! Run `npm login` to login and create this file by closing the opened browser.');
}
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({
channel: 'chrome',
headless: false,
});
// https://github.com/berstend/puppeteer-extra/issues/454#issuecomment-917437212
const originalUserAgent = await (await (await browser.newContext()).newPage()).evaluate(() => { return navigator.userAgent });
console.log(originalUserAgent);
const context = await browser.newContext({
storageState: 'auth.json',
viewport: { width: 1280, height: 1280 },
userAgent: originalUserAgent.replace("Headless", ""),
});
const enabledEvasions = [
'chrome.app',
'chrome.csi',
'chrome.loadTimes',
'chrome.runtime',
'iframe.contentWindow',
'media.codecs',
'navigator.hardwareConcurrency',
'navigator.languages',
'navigator.permissions',
'navigator.plugins',
'navigator.webdriver',
'sourceurl',
// 'user-agent-override', // doesn't work since playwright has no page.browser()
'webgl.vendor',
'window.outerdimensions'
];
const evasions = enabledEvasions.map(e => new require(`puppeteer-extra-plugin-stealth/evasions/${e}`));
const stealth = {
callbacks: [],
async evaluateOnNewDocument(...args) {
this.callbacks.push({ cb: args[0], a: args[1] })
}
}
evasions.forEach(e => e().onPageCreated(stealth));
for (let evasion of stealth.callbacks) {
await context.addInitScript(evasion.cb, evasion.a);
}
const page = await context.newPage();
await page.goto('https://www.epicgames.com/store/en-US/free-games');
// await expect(page.locator('a[role="button"]:has-text("Sign In")')).toHaveCount(0);
await page.click('button:has-text("Accept All Cookies")'); // to not waste screen space in --debug
await page.click('[data-testid="offer-card-image-landscape"]');
// TODO check if already claimed
await page.click('[data-testid="purchase-cta-button"]');
await page.click('button:has-text("Continue")');
// it then creates an iframe for the rest
// await page.frame({ url: /.*store\/purchase.*/ }).click('button:has-text("Place Order")'); // not found because it does not wait for iframe
const iframe = page.frameLocator('.webPurchaseContainer iframe')
await iframe.locator('button:has-text("Place Order")').click();
await iframe.locator('button:has-text("I Agree")').click();
await page.pause();
await context.close();
await browser.close();
})();

142
package-lock.json generated
View file

@ -9,7 +9,8 @@
"@playwright/test": "^1.17.1", "@playwright/test": "^1.17.1",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"playwright": "^1.17.1", "playwright": "^1.17.1",
"playwright-extra": "^4.2.1-next.616" "playwright-extra": "^4.2.1-next.616",
"puppeteer-extra-plugin-stealth": "^2.9.0"
} }
}, },
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
@ -1601,6 +1602,20 @@
"dev": true, "dev": true,
"peer": true "peer": true
}, },
"node_modules/fs-extra": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
"integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==",
"dev": true,
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/fs.realpath": { "node_modules/fs.realpath": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@ -2161,6 +2176,18 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dev": true,
"dependencies": {
"universalify": "^2.0.0"
},
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/kind-of": { "node_modules/kind-of": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@ -2712,6 +2739,49 @@
"puppeteer-extra": "*" "puppeteer-extra": "*"
} }
}, },
"node_modules/puppeteer-extra-plugin-stealth": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/puppeteer-extra-plugin-stealth/-/puppeteer-extra-plugin-stealth-2.9.0.tgz",
"integrity": "sha512-erZ9lkIcOkfYmLPP2jv2AiqvNBFhQJinWJhcm40pqSjwJTsZXHsTARUyRCsBYEEBvNIs3Wz3E0zVlTRc4IJ6Hg==",
"dev": true,
"dependencies": {
"debug": "^4.1.1",
"puppeteer-extra-plugin": "^3.2.0",
"puppeteer-extra-plugin-user-preferences": "^2.3.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/puppeteer-extra-plugin-user-data-dir": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/puppeteer-extra-plugin-user-data-dir/-/puppeteer-extra-plugin-user-data-dir-2.3.1.tgz",
"integrity": "sha512-yhaYMaNFdfQ1LbA94ZElW1zU8rh+MFmO+GZA0gtQ8BXc+UZ6aRrWS9flIZvlXDzk+ZsXhCbTEohEwZ8lEDLRVA==",
"dev": true,
"dependencies": {
"debug": "^4.1.1",
"fs-extra": "^10.0.0",
"puppeteer-extra-plugin": "^3.2.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/puppeteer-extra-plugin-user-preferences": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/puppeteer-extra-plugin-user-preferences/-/puppeteer-extra-plugin-user-preferences-2.3.1.tgz",
"integrity": "sha512-t/FyGQj2aqtHOROqL02z+k2kNQe0cjT0Hd9pG5FJ7x0JXx1722PhOuK7FeJLQMJ+BLl2YvCUgaWSC8Zohjts5A==",
"dev": true,
"dependencies": {
"debug": "^4.1.1",
"deepmerge": "^4.2.2",
"puppeteer-extra-plugin": "^3.2.0",
"puppeteer-extra-plugin-user-data-dir": "^2.3.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/puppeteer/node_modules/debug": { "node_modules/puppeteer/node_modules/debug": {
"version": "4.3.2", "version": "4.3.2",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
@ -3066,6 +3136,15 @@
"through": "^2.3.8" "through": "^2.3.8"
} }
}, },
"node_modules/universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
"dev": true,
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/util-deprecate": { "node_modules/util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@ -4334,6 +4413,17 @@
"dev": true, "dev": true,
"peer": true "peer": true
}, },
"fs-extra": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
"integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
}
},
"fs.realpath": { "fs.realpath": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@ -4736,6 +4826,16 @@
"minimist": "^1.2.5" "minimist": "^1.2.5"
} }
}, },
"jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.6",
"universalify": "^2.0.0"
}
},
"kind-of": { "kind-of": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@ -5181,6 +5281,40 @@
"merge-deep": "^3.0.1" "merge-deep": "^3.0.1"
} }
}, },
"puppeteer-extra-plugin-stealth": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/puppeteer-extra-plugin-stealth/-/puppeteer-extra-plugin-stealth-2.9.0.tgz",
"integrity": "sha512-erZ9lkIcOkfYmLPP2jv2AiqvNBFhQJinWJhcm40pqSjwJTsZXHsTARUyRCsBYEEBvNIs3Wz3E0zVlTRc4IJ6Hg==",
"dev": true,
"requires": {
"debug": "^4.1.1",
"puppeteer-extra-plugin": "^3.2.0",
"puppeteer-extra-plugin-user-preferences": "^2.3.1"
}
},
"puppeteer-extra-plugin-user-data-dir": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/puppeteer-extra-plugin-user-data-dir/-/puppeteer-extra-plugin-user-data-dir-2.3.1.tgz",
"integrity": "sha512-yhaYMaNFdfQ1LbA94ZElW1zU8rh+MFmO+GZA0gtQ8BXc+UZ6aRrWS9flIZvlXDzk+ZsXhCbTEohEwZ8lEDLRVA==",
"dev": true,
"requires": {
"debug": "^4.1.1",
"fs-extra": "^10.0.0",
"puppeteer-extra-plugin": "^3.2.0"
}
},
"puppeteer-extra-plugin-user-preferences": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/puppeteer-extra-plugin-user-preferences/-/puppeteer-extra-plugin-user-preferences-2.3.1.tgz",
"integrity": "sha512-t/FyGQj2aqtHOROqL02z+k2kNQe0cjT0Hd9pG5FJ7x0JXx1722PhOuK7FeJLQMJ+BLl2YvCUgaWSC8Zohjts5A==",
"dev": true,
"requires": {
"debug": "^4.1.1",
"deepmerge": "^4.2.2",
"puppeteer-extra-plugin": "^3.2.0",
"puppeteer-extra-plugin-user-data-dir": "^2.3.1"
}
},
"react-is": { "react-is": {
"version": "17.0.2", "version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@ -5421,6 +5555,12 @@
"through": "^2.3.8" "through": "^2.3.8"
} }
}, },
"universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
"dev": true
},
"util-deprecate": { "util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",

View file

@ -4,13 +4,15 @@
"codegen": "npx playwright codegen --load-storage=auth.json https://www.epicgames.com/store/en-US/free-games", "codegen": "npx playwright codegen --load-storage=auth.json https://www.epicgames.com/store/en-US/free-games",
"start": "npx playwright test --timeout 10000", "start": "npx playwright test --timeout 10000",
"debug": "npx playwright test --debug", "debug": "npx playwright test --debug",
"captcha": "node main.captcha" "captcha": "node main.captcha",
"stealth": "node main.stealth"
}, },
"devDependencies": { "devDependencies": {
"@extra/recaptcha": "^4.2.1-next.616", "@extra/recaptcha": "^4.2.1-next.616",
"@playwright/test": "^1.17.1", "@playwright/test": "^1.17.1",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"playwright": "^1.17.1", "playwright": "^1.17.1",
"playwright-extra": "^4.2.1-next.616" "playwright-extra": "^4.2.1-next.616",
"puppeteer-extra-plugin-stealth": "^2.9.0"
} }
} }