60

Using puppeteer, how could you programmatically submit a form? So far I've been able to do this using page.click('.input[type="submit"]') if the form actually includes a submit input. But for forms that don't include a submit input, focusing on the form text input element and using page.press('Enter') doesn't seem to actually cause the form to submit:

const puppeteer = require('puppeteer');

(async() => {

    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('https://stackoverflow.com/', {waitUntil: 'load'});
    console.log(page.url());

    // Type our query into the search bar
    await page.focus('.js-search-field');
    await page.type('puppeteer');

    // Submit form
    await page.press('Enter');

    // Wait for search results page to load
    await page.waitForNavigation({waitUntil: 'load'});


    console.log('FOUND!', page.url());

    // Extract the results from the page
    const links = await page.evaluate(() => {
      const anchors = Array.from(document.querySelectorAll('.result-link a'));
      return anchors.map(anchor => anchor.textContent);
    });
    console.log(links.join('\n'));
    browser.close();

})();
nwxdev
  • 4,194
  • 3
  • 16
  • 22
docta_faustus
  • 2,383
  • 4
  • 30
  • 47

3 Answers3

81

If you are attempting to fill out and submit a login form, you can use the following:

await page.goto('https://www.example.com/login');

await page.type('#username', 'username');
await page.type('#password', 'password');

await page.click('#submit');

await page.waitForNavigation();

console.log('New Page URL:', page.url());
Grant Miller
  • 27,532
  • 16
  • 147
  • 165
  • 2
    Keep in mind that if the inputs already have content like in the case of updating a form, this method will prepend the data already in the input field. – mckenna Jul 11 '19 at 19:29
  • 4
    @mckenna "Another interesting solution is to click the target field 3 times so that the browser would select all the text in it and then you could just type what you want:" `await input.click({ clickCount: 3 })` : https://stackoverflow.com/a/52633235/556169 – Eray Sep 24 '20 at 11:09
44

Try this

const form = await page.$('form-selector');
await form.evaluate(form => form.submit());

For v0.11.0 and laters:

await page.$eval('form-selector', form => form.submit());
Nam Mai Anh
  • 629
  • 8
  • 9
2

I was scraping a SPA, and I had to use waitForNetworkIdle since the form submit was not triggering a page navigation event. Instead it submitted data to the server, and updated the DOM of the page which was already loaded.

const [response] = await Promise.all([        
    page.waitForNetworkIdle(),
    page.click('#form-submit-button'),
]);

When to use waitForNetworkIdle

I suspect that if you open a normal web browser, submit the form, and look to see if the page URL has changed or not. If it has not changed, you should use waitForNetworkIdle.

Also, take this advice with a grain of salt, I've only been using puppeteer for an hour.

Walter Stabosz
  • 7,447
  • 5
  • 43
  • 75