145

In puppeteer I would like to wait a defined time before going to the next line of code.

I've tried to put a setTimeout in an evaluate function but it seems to be simply ignored

console.log('before waiting');
await page.evaluate(async() => {
  setTimeout(function(){
      console.log('waiting');
  }, 4000)
});
console.log('after waiting');

This code don't wait and just write before waiting and after waiting

Do you know how to do this?

Benjamin
  • 5,783
  • 4
  • 25
  • 49
Pipo
  • 5,170
  • 7
  • 33
  • 66
  • await page.evaluate(async() => { setTimeout(function(){ console.log('waiting'); }, 4000);}); your code is not right , above is the right – Osama Oct 24 '17 at 20:03

8 Answers8

227

You can use a little promise function,

function delay(time) {
   return new Promise(function(resolve) { 
       setTimeout(resolve, time)
   });
}

Then, call it whenever you want a delay.

console.log('before waiting');
await delay(4000);
console.log('after waiting');

If you must use puppeteer use the builtin waitForTimeout function.

await page.waitForTimeout(4000)

If you still want to use page.evaluate, resolve it after 4 seconds. You are not resolving anything.

await page.evaluate(async() => {
    await new Promise(function(resolve) { 
           setTimeout(resolve, 1000)
    });
});

But I guess you can simply use the first two examples.

Md. Abu Taher
  • 17,395
  • 5
  • 49
  • 73
118

I've been using:

await page.waitForTimeout(3000);

Where 3000 is Milliseconds And that seems to be working for me.

Benny Code
  • 51,456
  • 28
  • 233
  • 198
Huckleberry Carignan
  • 2,002
  • 4
  • 17
  • 33
59

You can use one of the following options to wait for one second:

await page.waitFor(1000);
await frame.waitFor(1000);
await new Promise(r => setTimeout(r, 1000));

Alternatively, there are many Puppeteer functions that include a built-in delay option, which may come in handy for waiting between certain events:

// Click Delay
// Time to wait between mousedown and mouseup in milliseconds. Defaults to 0.

await page.click('#example', {delay: 1000});
await frame.click('#example', {delay: 1000});
await elementHandle.click({delay: 1000});
await page.mouse.click(0, 0, {delay: 1000});

// Type Delay
// Time to wait between key presses in milliseconds. Defaults to 0.

await page.type('#example', 'Hello, world!', {delay: 1000});
await frame.type('#example', 'Hello, world!', {delay: 1000});
await elementHandle.type('Hello, world!', {delay: 1000});
await page.keyboard.type('Hello, world!', {delay: 1000});

// Press Delay
// Time to wait between keydown and keyup in milliseconds. Defaults to 0.

await elementHandle.press('Backspace', {delay: 1000});
await page.keyboard.press('Backspace', {delay: 1000});
Grant Miller
  • 27,532
  • 16
  • 147
  • 165
27

page.waitFor has now been deprecated.

page.waitForTimeout is now advised to pause script execution for the given number of milliseconds before continuing:

await page.waitForTimeout(1000)
MatthewThomas.dev
  • 1,045
  • 10
  • 24
10

Other answers have shown how to sleep, but now that page.waitForTimeout is finally deprecated, I figure I'd add the answer I've wanted to add for awhile:

Don't sleep! It causes a race condition that disrupts the event-driven nature of Puppeteer, introducing unnecessary brittleness. There's almost always a better predicate to wait on, either explicitly or using the Locator API:

  • Are you waiting for a CSS selector, aria label, text or XPath to appear? Try waitForSelector (optionally with the appropriate built-in selector).
  • Are you waiting for a navigation? Try waitForNavigation or adjust the waitUntil option on goto.
  • Are you waiting for a network event or state? Try waitForRequest, waitForResponse or waitForNetworkIdle.
  • Are you waiting for a popup? Try promisifying page.on("dialog", ....
  • Are you waiting for some arbitrary predicate, like a minimum number of child elements to appear? Try waitForFunction.
  • Are you trying to avoid detection? Try slowMo.
  • Something else? Run an evaluate block and add your own code to wait for a DOM mutation or poll with setInterval or requestAnimationFrame and effectively reimplement waitForFunction as fits your needs.

waitForFunction in particular is underused but it adds a huge amount of reliability and precision that waitForTimeout doesn't.

If all else fails and you have to block the script, you can delay, but I've written hundreds of Puppeteer scripts and have never had to use any sleep variant, so I'm pretty convinced it's basically unnecessary.

See my blog post on Puppeteer Antipatterns for more analysis of why you should avoid sleeping in any form except as an absolute last resort.

See also the Playwright docs for waitForTimeout, which is essentially the same as the Puppeteer method:

Discouraged

Never wait for timeout in production. Tests that wait for time are inherently flaky. Use Locator actions and web assertions that wait automatically.

One caveat to the above: sleeping can be useful for temporary debugging while developing a script.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
  • 1
    100% agree with this line "waitForFunction in particular is underused but it adds a huge amount of reliability and precision that waitForTimeout doesn't." – Moinul Moin Mar 11 '23 at 08:18
4

Try this function.

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

to use it

  async function demo() {
    console.log('Waiting...');
    await sleep(3000);
    console.log('ok');
  }

  demo();
Yordan
  • 88
  • 6
-1
await new Promise(_func=> setTimeout(_func, 5000));
Xin
  • 33,823
  • 14
  • 84
  • 85
  • Many other answers already offer this with a clear explanation. Renaming `resolve` to `_func` is odd. Not only that, we really shouldn't be using this in Puppeteer anyway if we can possibly help it. – ggorlen Dec 08 '22 at 18:37
-4

Your syntax is incomplete.
Try this...

await page.evaluate(async() => {
    setTimeout(function(){
        console.log('waiting');
    }, 4000)
});
atopcu
  • 214
  • 1
  • 8
  • thank for your help ,i edited the question , sorry for the litle mistake but i really ask how to wait – Pipo Oct 24 '17 at 20:11