Unable to login with Puppeteer - node.js

I am trying to login to Moz at https://moz.com/login with Puppeteer using the following code:
const puppeteer = require('puppeteer');
const creds = {
email: "myemail",
password: "mypassword"
};
(async () => {
const browser = await puppeteer.launch({
args: [
'--disable-web-security',
],
headless: false
});
const page = await browser.newPage();
await page.goto("https://moz.com/login");
await page.$eval("input[name=email]", (el, value) => el.value = value, creds.email);
await page.$eval("input[name=password]", (el, value) => el.value = value, creds.password);
await Promise.all([
page.$eval("input[type=submit]", elem => elem.click()),
page.waitForNavigation({ waitUntil: 'networkidle0' }),
]);
await browser.close();
})();
I know that the email and password I am passing are correct, because I can use them to login manually, but when I run the script above, I get an "Invalid email or password" error above the form.
There are two errors logged to the JS console in Chrome:
Failed to load resource: the server Failed to load resource: the server responded with a status of 404 ()
cs.moz.com/id?d_visid_ver=1.10.0&d_fieldgroup=A&mcorgid=2C702C1653CF9B460A490D4B%40AdobeOrg&mid=86471825972219878023490878783607186756&ts=1564059866100:1
and
Failed to load resource: the server responded with a status of 400 () svc/forge/forms/login:1
Any ideas as to what the issue could be?

This error occurred because you are setting email and password by executing a javascript function $eval instead of the type function.
Also, I would suggest using the click function instead of the $eval function. Read more about the difference between a "trusted" and "untrusted" input event
just replace these lines:
await page.$eval("input[name=email]", (el, value) => el.value = value, creds.email);
await page.$eval("input[name=password]", (el, value) => el.value = value, creds.password);
with these:
await page.type('input[name=email]', creds.email);
await page.type('input[name=password]', creds.password)
So your final script should be:
const puppeteer = require('puppeteer');
const creds = {
email: "myemail",
password: "mypassword"
};
(async () => {
const browser = await puppeteer.launch({
args: [
'--disable-web-security',
],
headless: false
});
const page = await browser.newPage();
await page.goto("https://moz.com/login");
await page.type('input[name=email]', creds.email);
await page.type('input[name=password]', creds.password)
await Promise.all([
page.click('input[type=submit]'),
page.waitForNavigation({ waitUntil: 'networkidle0' }),
]);
await browser.close();
})();

Related

How to login to google account with playwright?

I have following source code and run it in headful mode.
I can input email address.
But, after that, there is message that saying "Couldn't sign you in.For your protection, you can't sign in from this device. Try again later, or sign in from another device.".
Do I need to set additional header or something else?
Here is my source code.
const playwright = require('playwright');
const cookiePath = '/home/ubuntu/.config/chromium/Default';
browser['chromium'] = await playwright['chromium'].launchPersistentContext(cookiePath,{
headless: false,
args: [
`--disable-extensions-except=${pathToExtension}`,
`--load-extension=${pathToExtension}`,
],
});
const page = await browser['chromium'].newPage();
const login_url = "https://accounts.google.com/signin/v2/identifier?hl=ja&flowName=GlifWebSignIn&flowEntry=ServiceLogin";
await page.goto(login_url);
await page.fill('#identifierId',userinfo['id']);
await page.click("#identifierNext");
await page.fill('[name=password]',userinfo['password']);
await page.click("#passwordNext");
My solution:
const { chromium } = require("playwright");
(async () => {
const browser = await chromium.launch({
headless: false,
args: ["--disable-dev-shm-usage"],
});
const context = await browser.newContext({});
const page = await context.newPage();
const navigationPromise = page.waitForNavigation({
waitUntil: "domcontentloaded",
});
await page.setDefaultNavigationTimeout(0);
await page.goto(
"https://accounts.google.com/signin/v2/identifier?hl=en&flowName=GlifWebSignIn&flowEntry=ServiceLogin"
);
await navigationPromise;
await page.waitForSelector('input[type="email"]');
await page.type('input[type="email"]', "youremail");
await page.click("#identifierNext");
await page.waitForSelector('input[type="password"]', { visible: true });
await page.type('input[type="password"]', "yourpassword");
await page.waitForSelector("#passwordNext", { visible: true });
await page.click("#passwordNext");
await navigationPromise;
//you are in
I think you can search for login to google with Puppeteer also.
This works for me:
add --disable-blink-features=AutomationControlled to your args.
This works for me:
const browser = await playwright.chromium.launch({
ignoreDefaultArgs: ['--disable-component-extensions-with-background-pages']
})

puppeteer writing in the label doesn't work pop up

I'm creating a bot to enter the site.
After opening the popup I have 2 fields, emailAddress and password. Both have random id and only name value.
The emailAddress is not completing. But the password works normally(completing).
This is a part my code
//open poupup
await page.$eval( '#anchor-open', form => form.click() );
//wait for the screen to load
await page.waitForSelector('input[name="emailAddress"]');
//write in the fields
await page.type('input[name="emailAddress"]', '22#d.com', {delay: 100});
await page.type('input[name="password"]', '****************', {delay: 100});
Can someone help me?
You need to wait for domcontentloaded event. then wait for #anchor-acessar element before click it.
The code below working fine with me.
const puppeteer = require("puppeteer");
(async () => {
const browser = await puppeteer.launch({
headless: false,
});
const page = await browser.newPage();
await page.goto("https://www.nike.com.br", {
waitUntil: "domcontentloaded",
});
await page.waitForSelector('#anchor-acessar');
await page.$eval("#anchor-acessar", (form) => form.click());
await page.waitForSelector('input[name="emailAddress"]');
await page.type('input[name="emailAddress"]', "22#d.com", { delay: 100 });
await page.type('input[name="password"]', "****************", { delay: 100 });
await page.keyboard.press('Enter');
// await browser.close();
})();

Click checkbox with puppeteer via element ID

I have this puppeteer code:
(async () => {
const browser = await puppeteer.launch({ args: ['--no-sandbox'] });
const page = await browser.newPage();
await page.goto("https://myurl.com/page");
await page.waitForSelector("#select-all-checkbox");
var bodyHTML = await page.content();
console.log(bodyHTML + "\n\n");
await page.click("#select-all-checkbox");
await page.close();
await browser.close();
})();
Logging the HTML to the console, I have verified the page I am accessing has this HTML:
<label><input type="checkbox" name="" id="select-all-checkbox" value="" checked=""><span class="ifaFs"><span data-testid="icon-checkbox-someselected" class="hdDWuD"></span></span></label>
I am receiving this error on the page.click line:
(node:3827) UnhandledPromiseRejectionWarning: Error: Node is either
not visible or not an HTMLElement
at ElementHandle._clickablePoint (/path/to/node_modules/puppeteer/lib/JSHandle.js:217:13)
at process._tickCallback (internal/process/next_tick.js:68:7)
-- ASYNC --
at ElementHandle. (/path/to/node_modules/puppeteer/lib/helper.js:111:15)
at DOMWorld.click (/path/to/node_modules/puppeteer/lib/DOMWorld.js:367:18)
at process._tickCallback (internal/process/next_tick.js:68:7)
-- ASYNC --
at Frame. (/path/to/node_modules/puppeteer/lib/helper.js:111:15)
at Page.click (/path/to/node_modules/puppeteer/lib/Page.js:1037:29)
With my code example above, this was how I resolved the problem.
(async () => {
const browser = await puppeteer.launch({ args: ['--no-sandbox'] });
const page = await browser.newPage();
await page.goto("https://myurl.com/page");
await page.waitForSelector("#select-all-checkbox");
await page.evaluate(() => {
document.querySelector("#select-all-checkbox").parentElement.click();
});
await page.close();
await browser.close();
})();
This approach worked for me:
(async () => {
const browser = await puppeteer.launch({ args: ['--no-sandbox'] });
const page = await browser.newPage();
await page.goto("https://myurl.com/page");
const checkboxEl = await page.waitForSelector("#select-all-checkbox");
checkboxEl.click();
await page.close();
await browser.close();
})();

How to trigger "Followers" modal on Instagram?

I can't get my puppet to click on the "Followers" link in Instagram.
I assume that Instagram has done some anti-bot magic, but maybe I'm just too conspiratory about it.
How could I get the "Followers" modal to show?
This is my code:
const puppeteer = require('puppeteer');
var instagram = {
username: 'username',
password: 'password'
}
var run = ()=>{
(async () => {
const browser = await puppeteer.launch({headless: false, args: ['--lang=en-EN,en']});
const page = await browser.newPage();
await page.setExtraHTTPHeaders({ 'Accept-Language': 'en' });
await page.goto('https://www.instagram.com/accounts/login');
await page.waitFor(1500);
await page.click("input[type=\"text\"]")
await page.keyboard.type(instagram.username);
await page.click("input[type=\"password\"]")
await page.keyboard.type(instagram.password);
await page.click("button[type=\"submit\"]");
await page.waitForNavigation();
await page.click(".HoLwm");
await page.click(".glyphsSpriteUser__outline__24__grey_9")
await page.waitForNavigation();
await page.waitFor(2500);
await page.waitForSelector('a.-nal3');
await page.evaluate(() => document.querySelector('a.-nal3')) //does not work
//await page.click(".-nal3") //does not work
await page.waitFor(3000);
await page.waitFor(1000);
//await browser.close();
})();
}
run()
While reviewing your script I noticed that not all of your selectors are the same in my Instagram so I fixed it trying not to use exact selectors since they may change tomorrow.
But this works today (see comments on what changed in the script):
var run = ()=>{
(async () => {
const browser = await puppeteer.launch({headless: false, args: ['--lang=en-EN,en']});
const rand = function(){ return Math.floor(1000 + Math.random() * 2000) }
const page = await browser.newPage();
await page.setExtraHTTPHeaders({ 'Accept-Language': 'en' });
await page.goto('https://www.instagram.com/accounts/login');
// When you can try not to `waitFor` set periods of time
// Wait for selectors, wait for random periods of time
await page.waitForSelector('button[type=\"submit\"]');
await page.click("input[type=\"text\"]")
await page.keyboard.type(instagram.username);
await page.waitFor(rand())
await page.click("input[type=\"password\"]")
await page.keyboard.type(instagram.password);
await page.waitFor(rand())
await page.click("button[type=\"submit\"]");
await page.waitForNavigation();
await page.waitFor(rand())
// After login we're back on the main page
// Wait till React starts and paints the interface
// We're waiting for "Profile" icon to be visible
await page.waitForSelector("span[aria-label='Profile']");
// Then we click on the link inside of which the icon is located
// That is link to the profile
await page.evaluate(() => document.querySelector("span[aria-label='Profile']").parentNode.click() );
await page.waitForNavigation();
await page.waitFor(rand())
// Do not rely on a selector
// Find a link that contains "followers" in its href
await page.waitForSelector("a[href*='followers']");
const followers = await page.evaluate(() => document.querySelector("a[href*='followers']").textContent)
console.log("Total followers: " + followers);
// Click on the followers link
await page.evaluate( () => document.querySelector("a[href*='followers']").click() )
// Wait for the followers modal and profiles
await page.waitFor("div[role='presentation'] div[role='dialog'] div:nth-child(2) ul li");
// Get followers that are in the list in the second div of that modal
const people = await page.evaluate(() => {
return [...document.querySelectorAll("div[role='presentation'] div[role='dialog'] div:nth-child(2) ul li")]
.map(user => {
const profLink = user.querySelector("a[title]")
return {
"name" : profLink.textContent,
"url" : profLink.href
};
})
})
console.log(people)
// await browser.close();
})();
}

Running a loop within an instance of Puppeteer

Just getting started with Puppeteer and i can launch the browser, go to a url, run a bunch of actions and then close the browser. What i am looking to see if i can do though is open the browser and loop over a set of actions in the same session.
I have a JSON object with urls i want to visit, so want to loop over that
// teams.js
module.exports = {
premier_league: [
{ team_name: "Team 1", url: "https://url-of-site/team_1"},
{ team_name: "Team 2", url: "https://url-of-site/team_2"}
]
}
My script to launch puppeteer is as follows
// index.js
const TEAM = require('./teams');
const puppeteer = require('puppeteer');
(async () => {
// Initialise Browser
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
await page.setViewport({
width: 1280,
height: 800
});
await page.goto('login page');
await page.click('login_box');
await page.keyboard.type('username');
await page.click('login_password');
await page.keyboard.type('password');
await page.click('login_button');
await page.waitForNavigation();
// Go To Team URL
await page.goto('Team URL')
await browser.close();
})();
So to loop over my JSON object I can use
Object.keys(TEAM['premier_league']).forEach(function(key) {
// Output url of each team
console.log(TEAM['premier_league'][key]['url'])
});
If i wrap my go to url with my loop, then page is no longer accessible
// index.js
const TEAM = require('./teams');
const puppeteer = require('puppeteer');
(async () => {
// Initialise Browser
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
await page.setViewport({
width: 1280,
height: 800
});
await page.goto('login page');
await page.click('login_box');
await page.keyboard.type('username');
await page.click('login_password');
await page.keyboard.type('password');
await page.click('login_button');
await page.waitForNavigation();
Object.keys(TEAM['premier_league']).forEach(function(key) {
// Go To Team URL
await page.goto(TEAM['premier_league'][key]['url'])
});
await browser.close();
})();
The actual error is
await page.goto(TEAM[args][key]['url'])
^^^^
SyntaxError: Unexpected identifier
Your Object.keys callback function need to use async as well in order to use await inside. Try to change as below
Object.keys(TEAM['premier_league']).forEach( async function(key) {
// Go To Team URL
await page.goto(TEAM['premier_league'][key]['url'])
});
Hope it helps

Resources