Demo code here

This is a handy little piece of code if you do any selling on Amazon or have been hired to do work for an ecommerce company. It's also very simple. It harnesses Puppeteer to open Amazon product details page and just grabs the buybox price for each.

I'm doing this in typescript with async / await. Check this for more explanation on async/await.

Because Puppeteer pretty much exclusively uses promises, I start the code with a self calling async function, like this:

(async () => {
  // awesome code here

})();

I also run a lot of my Puppeteer scrapers on a Digital Ocean (which I love) ubuntu box so I have a block at the top that makes Puppeteer work in ubuntu.

let browser: Browser;
let ubuntu = false;
let headless = false;
if (process.argv[2] === 'ubuntu' || process.argv[3] === 'ubuntu') {
	ubuntu = true;	
}
if (process.argv[2] === 'headless' || process.argv[3] === 'headless') {
	headless = true;
}
if (ubuntu) {
	browser = await puppeteer.launch({ headless: true, args: [`--window-size=${1800},${1200}`, '--no-sandbox', '--disable-setuid-sandbox'] });
}
else {
	browser = await puppeteer.launch({ headless: headless, args: [`--window-size=${1800},${1200}`] });
}

I've also added scripts in my package.json to run the code headless or on ubuntu automatically. It'll check to see if the argument passed to the script is 'ubuntu' or 'headless' and then handle it accordingly.

  "scripts": {
    "start": "tsc && node ./dist/index.js",
    "start:ubuntu": "tsc && node ./dist/index.js ubuntu",
    "start:headless": "tsc && node ./dist/index.js headless"
  },

Now to the fun, and easy, part! There is really only update you need to make to have this do what you want for your products. Just update the array of ASINs to be the ASINs you want scraped. An ASIN is an Amazon standard identification number and with that we can go directly to the product we are looking at. You can also find them very easily in your Amazon Seller Central inventory page.

If you are storing your ASINs in an external database here would be a good place to pull those and put them into the asins array.

const baseUrl = `https://www.amazon.com/dp/`;

// Whatever products you want to scrape
const asins = [ 'B0007L7GMW', 'B0007LHZCS', 'B0007LDX8I'];

Now, we just simply loop through the ASINs, go to our url that is concatenated with the base Amazon url of https://www.amazon.com/dp/ and the asin. I've built a few Puppeteer helpers and I use one here. It just grabs the element property that I want from the ElementHandle (the page) in this case and the selector. The helpers are part of the package.json and in the public npmjs so they'll automatically install with npm i if you use my code.

You can also of course just use the out of the box Puppeteer function which is where you get the elementhandle and then the property. I just found myself doing this over and over again. Here's the getPropertyBySelector fucntion if you just want to use the base Puppeteer functionality.

export async function getPropertyBySelector(handleOrPage: Page | ElementHandle | null, selector: string, property: string = '') {
    if (handleOrPage) {
        const handle = await handleOrPage.$(selector);
        if (handle) {
            return await (await handle.getProperty(property)).jsonValue();
        }
        else {
            return null;
        }
    }
    else {
        return null;
    }
}

Amazon makes it pretty easy with their CSS selectors and so we simply use them to get the buybox price and the current buybox vendor.

for (let asin of asins) {
    const url = baseUrl + asin;

    const page = await setUpNewPage(browser);
    await page.goto(url);
    const price = await getPropertyBySelector(page, '#priceblock_ourprice', 'innerHTML');
    const vendor = await getPropertyBySelector(page, '#merchant-info a', 'innerHTML');
    console.log('price, vendor', price, vendor);

    await page.close();

    // Update database or price or something else?
}

That's it! Done! You have prices AND the current buybox vendor for each.

Probably from here I'd activate my repricer if I didn't have the buybox to go and lower mine.

Demo code here