Skip to content

Instantly share code, notes, and snippets.

@hmmhmmhm
Forked from Brandawg93/google_login.ts
Created July 21, 2023 00:55
Show Gist options
  • Save hmmhmmhm/289c46b333d38aa8b3c5352fa4f2a4ff to your computer and use it in GitHub Desktop.
Save hmmhmmhm/289c46b333d38aa8b3c5352fa4f2a4ff to your computer and use it in GitHub Desktop.
Login to Google Account via Puppeteer
import puppeteer from 'puppeteer-extra';
import pluginStealth from 'puppeteer-extra-plugin-stealth'; // Use v2.4.5 instead of latest
import * as readline from 'readline';
puppeteer.use(pluginStealth());
// Use '-h' arg for headful login.
const headless = !process.argv.includes('-h');
// Prompt user for email and password.
const prompt = (query: string, hidden = false): Promise<string> =>
new Promise((resolve, reject) => {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
try {
if (hidden) {
const stdin = process.openStdin();
process.stdin.on('data', (char: string) => {
char = char + '';
switch (char) {
case '\n':
case '\r':
case '\u0004':
stdin.pause();
break;
default:
process.stdout.clearLine(0);
readline.cursorTo(process.stdout, 0);
process.stdout.write(query + Array(rl.line.length + 1).join('*'));
break;
}
});
}
rl.question(query, (value) => {
resolve(value);
rl.close();
});
} catch (err) {
reject(err);
}
});
// Launch puppeteer browser.
puppeteer.launch({ headless: headless }).then(async (browser: any) => {
console.log('Opening chromium browser...');
const page = await browser.newPage();
const pages = await browser.pages();
// Close the new tab that chromium always opens first.
pages[0].close();
await page.goto('https://accounts.google.com/signin/v2/identifier', { waitUntil: 'networkidle2' });
if (headless) {
// Only needed if sign in requires you to click 'sign in with google' button.
// await page.waitForSelector('button[data-test="google-button-login"]');
// await page.waitFor(1000);
// await page.click('button[data-test="google-button-login"]');
// Wait for email input.
await page.waitForSelector('#identifierId');
let badInput = true;
// Keep trying email until user inputs email correctly.
// This will error due to captcha if too many incorrect inputs.
while (badInput) {
const email = await prompt('Email or phone: ');
await page.type('#identifierId', email);
await page.waitFor(1000);
await page.keyboard.press('Enter');
await page.waitFor(1000);
badInput = await page.evaluate(() => document.querySelector('#identifierId[aria-invalid="true"]') !== null);
if (badInput) {
console.log('Incorrect email or phone. Please try again.');
await page.click('#identifierId', { clickCount: 3 });
}
}
const password = await prompt('Enter your password: ', true);
console.log('Finishing up...');
// Wait for password input
await page.type('input[type="password"]', password);
await page.waitFor(1000);
await page.keyboard.press('Enter');
// For headless mode, 2FA needs to be handled here.
// Login via gmail app works autmatically.
}
});
{
"displayName": "Puppeteer Google Login",
"name": "puppeteer-google-login",
"version": "1.0.0",
"description": "Login to your google account using puppeteer",
"main": "dist/login.js",
"scripts": {
"clean": "rimraf ./dist ./coverage",
"build": "rimraf ./dist ./coverage && tsc"
},
"engines": {
"node": ">=10"
},
"files": [
"dist/**/*"
],
"dependencies": {
},
"devDependencies": {
"@types/node": "14.0.11",
"@types/puppeteer": "^3.0.0",
"puppeteer": "^3.3.0",
"puppeteer-extra": "^3.1.9",
"puppeteer-extra-plugin-stealth": "^2.4.5",
"rimraf": "^3.0.2",
"typescript": "^3.8.3"
}
}
{
"compilerOptions": {
"target": "ES2018",
"module": "commonjs",
"lib": [
"ES2015",
"ES2016",
"ES2017",
"ES2018",
"dom"
],
"sourceMap": true,
"rootDir": "src",
"outDir": "dist",
"allowJs": true,
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
},
"include": [
"src"
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment