How to fix the TypeError ‘Cannot read property ‘download’ of undefined’ from browser.downloads.download using Puppeteer

Tags: , , , ,



I am using puppeteer to login into my account of a content provider I work with and download a lot of zips. I can easily get the array with all the links I need to download then I loop through the array and use browser.downloads.download (code taken from MDN) to download each link. The problem is that even before it starts to download it tells me:

error:  TypeError: Cannot read property 'download' of undefined

Here is my code:

const puppeteer = require('puppeteer');
require('dotenv').config();

(async () => {
  const browser = await puppeteer.launch({
    headless: false,
    args: ['--start-maximized'],
    defaultViewport: null,
  });

  const page = await browser.newPage();

  try {
    await page.goto(process.env.GROB_URL);
    page.setDefaultNavigationTimeout(0);

    await page.waitForSelector('input[name=user]', {
      visible: true,
    });
    //login
    await page.type('input[name=user]', process.env.GROB_USER);
    await page.type('input[name=pass]', process.env.GROB_PASS);
    await page.click('input#head-login');

    await page.waitForSelector('.light-highlight-row');

    const setValue = new Set();
    // get the nodelist array with all the download links
    let arr = await page.$$('.light-highlight-row td:nth-child(8) a');

    for (let item of arr) {
      const jsonValue = await item.getProperty('href');
      const value = await jsonValue.jsonValue();
      setValue.add(value);
    }
    
    const finalArray = Array.from(setValue);
    //all good till here

    function onStartedDownload(id) {
      console.log(`Started downloading: ${id}`);
    }

    function onFailed(error) {
      console.log(`Download failed: ${error}`);
    }

    //donwload all of them
    finalArray.forEach((link) => {
      var downloadUrl = link;
      var downloading = browser.downloads.download({
        url: downloadUrl,
      });
      downloading.then(onStartedDownload(link), onFailed(link));
    });
    page.waitForTimeout(500_000);

  } catch (error) {
    console.log('error: ', error);
  }
})();

It somehow tells me the browser is undefined, but it is JS API.

Answer

There is no this method or property downloads in Browse object, you can check it here on puppeteer docs.

you can try using a http request to get your files, for example using this strategy below, I couldn’t try it, but I hope it is usefull for you =)

 const puppeteer = require('puppeteer');
    require('dotenv').config();
    
    async function downloadFile(downloadUrl) {
        
       await fetch(downloadUrl)
            .then(res => res.blob())
            .then(blob => {
            var file = window.URL.createObjectURL(blob);
            window.location.assign(file);
        });
      
    }
    
    
    (async () => {
      const browser = await puppeteer.launch({
        headless: false,
        args: ['--start-maximized'],
        defaultViewport: null,
      });
    
      const page = await browser.newPage();
    
      try {
        await page.goto(process.env.GROB_URL);
        page.setDefaultNavigationTimeout(0);
    
        await page.waitForSelector('input[name=user]', {
          visible: true,
        });
        //login
        await page.type('input[name=user]', process.env.GROB_USER);
        await page.type('input[name=pass]', process.env.GROB_PASS);
        await page.click('input#head-login');
    
        await page.waitForSelector('.light-highlight-row');
    
        const setValue = new Set();
        // get the nodelist array with all the download links
        let arr = await page.$$('.light-highlight-row td:nth-child(8) a');
    
        for (let item of arr) {
          const jsonValue = await item.getProperty('href');
          const value = await jsonValue.jsonValue();
          setValue.add(value);
        }
        
        const finalArray = Array.from(setValue);
        //all good till here
    
        function onStartedDownload(id) {
          console.log(`Started downloading: ${id}`);
        }
    
        function onFailed(error) {
          console.log(`Download failed: ${error}`);
        }
    
        //donwload all of them
        finalArray.forEach((link) => {
           //here you can call the download funcion passing link and a filename
           await downloadFile(link)
        });
        page.waitForTimeout(500_000);
    
      } catch (error) {
        console.log('error: ', error);
      }
    })()


Source: stackoverflow