Unable to reference 'window' object inside exposeFunction() method when using Puppeteer

I’m working with a basic Puppeteer setup and trying to use exposeFunction() to execute code in headless Chrome. However, I keep running into issues when trying to access the window object from within the exposed function.

(async () => {
    const pup = require('puppeteer');
    const browser = await pup.launch();
    const newPage = await browser.newPage();

    const myExposedFunc = function() {
        return window.location.href;
    }

    await newPage.exposeFunction('myExposedFunc', myExposedFunc);

    const result = await newPage.evaluate(async () => {
        console.log('executing inside browser context');
        return await myExposedFunc();
    });

    console.log(result);
    await browser.close();
})();

This throws an error:

ReferenceError: window is not defined

The error points to my exposed function. What’s the correct way to access the window object within the headless browser environment?

I understand that using evaluate() works fine, but that approach doesn’t suit my needs when I need to pass functions dynamically:

(async () => {
    const pup = require('puppeteer');
    const browser = await pup.launch();
    const newPage = await browser.newPage();

    const result = await newPage.evaluate(async () => {
        console.log('this works fine');
        return window.location.href;
    });

    console.log(result);
    await browser.close();
})();

yeah, this trips ppl up initially. exposeFunction runs in node, not the browser. pass window data as params instead - call your exposed function with window.location.href from evaluate(), then handle the processing in node. just flip the approach around.

Had this exact problem when I started using Puppeteer heavily. The issue is exposeFunction creates a bridge going the wrong way for what you want. Your exposed function runs in Node.js, which doesn’t know about browser stuff like window, document, or localStorage. I fixed it by flipping the logic around. Instead of trying to grab browser data from inside the exposed function, pass that data in as parameters. So in your evaluate block, call myExposedFunc(window.location.href) and process the URL string in your Node.js function. This works great when you need heavy processing or file operations that can’t run in the browser. Another trick I’ve used is building dynamic evaluate strings for flexible function execution, though it gets messy from a code organization perspective.

You’re misunderstanding how exposeFunction() works. When you expose a function, it runs in Node.js on your host machine - not in the browser’s JavaScript environment. That’s why window is undefined. It doesn’t exist in Node.js. You need a different approach. Instead of trying to access browser objects from the exposed function, pass the data you need as parameters from the browser context. For example, modify your evaluate() call to pass window.location.href as an argument to your exposed function. If you need dynamic function execution within the browser context, try addFunction() or build your evaluate() calls dynamically with string templates. This keeps you in the browser context while still giving you flexible function definitions. The key thing to remember: exposed functions are bridges from browser to Node.js, not extensions of the browser environment.

This topic was automatically closed 4 days after the last reply. New replies are no longer allowed.