Skip to content

Instantly share code, notes, and snippets.

@jef
Last active July 29, 2022 15:28
Show Gist options
  • Star 41 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save jef/96fd50c6fe3eedc1bdf52585eac2b3c4 to your computer and use it in GitHub Desktop.
Save jef/96fd50c6fe3eedc1bdf52585eac2b3c4 to your computer and use it in GitHub Desktop.
const puppeteer = require("puppeteer");
const opn = require("opn");
const nodemailer = require("nodemailer");
const timeout = 5000;
const waitForTimeout = 1000;
const cartLink =
"https://store.nvidia.com/store/nvidia/en_US/buy/productID.5438481700/clearCart.yes/nextPage.QuickBuyCartPage";
const emailUsername = process.env.EMAIL_USERNAME;
const emailPassword = process.env.EMAIL_PASSWORD;
const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: emailUsername,
pass: emailPassword,
},
});
const mailOptions = {
from: emailUsername,
to: emailUsername,
subject: "NVIDIA - BUY NOW",
text: cartLink,
};
async function buy() {
const links = [
"https://www.nvidia.com/en-us/geforce/buy/",
"https://www.nvidia.com/en-us/shop/geforce/?page=1&limit=9&locale=en-us&search=3080",
"https://www.bestbuy.com/site/nvidia-geforce-rtx-3080-10gb-gddr6x-pci-express-4-0-graphics-card-titanium-and-black/6429440.p?skuId=6429440",
];
for (const link of links) {
await goto(link);
}
setTimeout(buy, timeout);
}
async function goto(link) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setUserAgent(
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
);
page.setViewport({
width: 1920,
height: 1080,
});
await page.goto(link);
await page.waitFor(waitForTimeout);
const dom = await page.evaluate(() => {
return {
body: document.body.innerText,
};
});
console.log(dom);
if (dom.body.toLowerCase().includes("out of stock") || dom.body.toLowerCase().includes("sold out")) {
console.log("still out of stock, will try again.");
} else {
console.log("*** IN STOCK, BUY NOW ***");
await page.screenshot({ path: `nvidia-${Date.now()}.png` });
opn(cartLink);
if (emailUsername && emailPassword) {
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
console.log(error);
} else {
console.log("email sent: " + info.response);
}
});
}
}
await browser.close();
}
try {
buy();
} catch (error) {
buy();
}
@andrewmackrodt
Copy link

andrewmackrodt commented Sep 22, 2020

Does anyone happen to have API Key that would work with GB store? It seems that my region FI/DN is in GB catalogue. I assume to find separate SKU for couple or regions in GB store.

Add &locale=en_gb to the digital river query string for GB listings, there are no 3090 cards right now and 3080 are out of stock.

@smithers54
Copy link

I would just like to say thank you to you and everyone else that helped make this script. I was able to combat the bots and get a card through newegg!!

@tashrifsanil
Copy link

I tried looking for the digitialRiverId of the 3090 by filtering out the json output from this "https://api.nvidia.partners/edge/product/search?page=1&limit=9&locale=en-ca&category=GPU&manufacturer=NVIDIA&gpu=RTX%203090". But it wasn't updated and the card is now sold out :( If anyone finds the digitalriverid that'd be legendary. The hunt continues

@andrewmackrodt
Copy link

@tashrifsanil you can get it from the landing page e.g. inspect the source of https://www.nvidia.com/en-gb/geforce/graphics-cards/30-series/rtx-3090/ - change "en-gb" to whatever is correct for your locale. Query selector is: div[data-digital-river-id].

@tashrifsanil
Copy link

@andrewmackrodt Yeah I think I found it, I'm pretty sure it's "5438792700"

@tashrifsanil
Copy link

@andrewmackrodt My badd I was wrong, I got that ^^ id by looking at requests made in network tab. Your method returned a proper id "5438481600" (for the us site). Thanks!!

@tashrifsanil
Copy link

Does anyone have a better way to check for stock? I was sending a get request to https://api-prod.nvidia.com/direct-sales-shop/DR/products/en_us/USD/5438481600 which would return a json response which would tell you inventory status, but now it doesn't work so well (error 503 - gateway times out).

Nvidia's own website makes the same website and now it fails there too, but eventually after a while the out of stock button pops up on their site. Do you guys think their website is setup so that if the request fails the out of stock button shows up? Or is their a better way to check for stock?

import requests

url = "https://api-prod.nvidia.com/direct-sales-shop/DR/products/en_us/USD/5438481600"

payload = {}
headers = {
  'authority': 'api-prod.nvidia.com',
  'accept': 'application/json, text/javascript, */*; q=0.01',
  'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36',
  'dnt': '1',
  'origin': 'https://www.nvidia.com',
  'sec-fetch-site': 'same-site',
  'sec-fetch-mode': 'cors',
  'sec-fetch-dest': 'empty',
  'referer': 'https://www.nvidia.com/en-us/geforce/graphics-cards/30-series/rtx-3090/',
  'accept-language': 'en-CA,en-GB;q=0.9,en-US;q=0.8,en;q=0.7'
}

response = requests.request("GET", url, headers=headers, data = payload)

print(response.text.encode('utf8'))

@tashrifsanil
Copy link

Okay so the above worked ^^ but the card was scalped again before I could check out :(

@jgramling17
Copy link

Does anyone have a better way to check for stock? I was sending a get request to https://api-prod.nvidia.com/direct-sales-shop/DR/products/en_us/USD/5438481600 which would return a json response which would tell you inventory status, but now it doesn't work so well (error 503 - gateway times out).

Nvidia's own website makes the same website and now it fails there too, but eventually after a while the out of stock button pops up on their site. Do you guys think their website is setup so that if the request fails the out of stock button shows up? Or is their a better way to check for stock?

import requests

url = "https://api-prod.nvidia.com/direct-sales-shop/DR/products/en_us/USD/5438481600"

payload = {}
headers = {
  'authority': 'api-prod.nvidia.com',
  'accept': 'application/json, text/javascript, */*; q=0.01',
  'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36',
  'dnt': '1',
  'origin': 'https://www.nvidia.com',
  'sec-fetch-site': 'same-site',
  'sec-fetch-mode': 'cors',
  'sec-fetch-dest': 'empty',
  'referer': 'https://www.nvidia.com/en-us/geforce/graphics-cards/30-series/rtx-3090/',
  'accept-language': 'en-CA,en-GB;q=0.9,en-US;q=0.8,en;q=0.7'
}

response = requests.request("GET", url, headers=headers, data = payload)

print(response.text.encode('utf8'))

Do you have a sample of what the json response structure looks like?

@tashrifsanil
Copy link

@jgramling17 I'll put up the json response when it's not timing out anymore. Till then if it helps, converting the json response using json.loads() and using this is how I'm check for when it's in stock
json_resp["products"]["product"][0]["inventoryStatus"]["status"] != 'PRODUCT_INVENTORY_OUT_OF_STOCK'

@jcharnley
Copy link

jcharnley commented Oct 2, 2020

where do we get the api key from for the store?

the only endpoint I can hit is https://api.nvidia.partners/edge/product/search?page=1&limit=9&locale=en-gb&category=GPU&manufacturer=NVIDIA&gpu=RTX%203080, which doesnt show stock levels.

anyone got a digital rivers endpoint that is working please? am sick of refeshing for days and days and missing out. want to write my own script

@jgramling17
Copy link

@jgramling17 I'll put up the json response when it's not timing out anymore. Till then if it helps, converting the json response using json.loads() and using this is how I'm check for when it's in stock
json_resp["products"]["product"][0]["inventoryStatus"]["status"] != 'PRODUCT_INVENTORY_OUT_OF_STOCK'

Awesome, that should be good for now, thanks so much! I'm getting repeated 504s from their api endpoint as well. Hopefully it'll go up before they go on sale again. I noticed that the 3080 availability page is no longer hitting that endpoint, wonder if it only checks around the time of new inventory.

where do we get the api key from for the store?

the only endpoint I can hit is https://api.nvidia.partners/edge/product/search?page=1&limit=9&locale=en-gb&category=GPU&manufacturer=NVIDIA&gpu=RTX%203080, which doesnt show stock levels.

anyone got a digital rivers endpoint that is working please? am sick of refeshing for days and days and missing out. want to write my own script

I assume they've locked it down and are concealing their digital river key on server side. The link above doesn't work anymore since they probably removed that key. If you look at digital-river's api reference it seems like you need to be using their service to obtain an api key, and even then I assume you would need the correct permissions to access nvidia's products. Purely speculation though.

@tashrifsanil
Copy link

@jgramling17 No worries, Lemme know if you manage to cop one! The 3090 got scalped again when it came back in stock last Thursday sighh

@Michael-Keen-MS
Copy link

yeah i am trying to figure out the DE location but there is nothing :(
https://in-and-ru-store-api.uk-e1.cloudhub.io/DR/products/de_de/EUR/5438481700
https://in-and-ru-store-api.uk-e1.cloudhub.io/DR/get-inventory/de_de/5438481700?format=json&expand=availablequantity
Also here:
https://api.nvidia.partners/edge/product/search?page=1&limit=9&locale=de-de
It looks like Germany never had any to start with :/

I believe different regions have different product IDs. en_gb (UK) is different than ours in US, just an FYI

Does this help?

{
"en-us": {
"rtx-3090": "5438481600",
"rtx-3080": "5438481700",
"rtx-3070": null,
"titan-rtx": "5254456900",
"rtx-2080-super": "5335703700",
"rtx-2070-super": "5394901600",
"rtx-2060-super": "5394902900",
"expensive-shirt": "5444021500"
},
"fr-fr": {
"rtx-3090": "5438761500",
"rtx-3080": "5438795200",
"rtx-3070": null,
"titan-rtx": "5256301100",
"rtx-2080-super": "5336531100",
"rtx-2070-super": "5394901900",
"rtx-2060-super": "5394903200",
"expensive-shirt": "5444021500"
},
"de-de": {
"rtx-3090": "5438761400",
"rtx-3080": "5438792300",
"rtx-3070": null,
"titan-rtx": "5256301000",
"rtx-2080-super": "5335703700",
"rtx-2070-super": "5394901600",
"rtx-2060-super": "5394902900",
"expensive-shirt": "5444021500"
},
"en-gb": {
"rtx-3090": "5438792700",
"rtx-3080": "5438792800",
"rtx-3070": null,
"titan-rtx": "5256301200",
"rtx-2080-super": "5336531200",
"rtx-2070-super": "5394902000",
"rtx-2060-super": "5394903300",
"expensive-shirt": "5444021500"
},
"es-es": {
"rtx-3090": "5438794700",
"rtx-3080": "5438794800",
"rtx-3070": null,
"titan-rtx": "5256301400",
"rtx-2080-super": "5336531400",
"rtx-2070-super": "5394901700",
"rtx-2060-super": "5394903000",
"expensive-shirt": "5444021500"
},
"it-it": {
"rtx-3090": "5438796100",
"rtx-3080": "5438796200",
"rtx-3070": null,
"titan-rtx": "5256302000",
"rtx-2080-super": "5336532000",
"rtx-2070-super": "5394902100",
"rtx-2060-super": "5394903400",
"expensive-shirt": "5444021500"
},
"pl-pl": {
"rtx-3090": "5438797600",
"rtx-3080": "5438797700",
"rtx-3070": null,
"titan-rtx": "5256301600",
"rtx-2080-super": "5336531600",
"rtx-2070-super": "5394902300",
"rtx-2060-super": "5394903700",
"expensive-shirt": "5444021500"
},
"nb-no": {
"rtx-3090": "5438797100",
"rtx-3080": "5438797200",
"rtx-3070": null,
"titan-rtx": "5256301700",
"rtx-2080-super": "5336531700",
"rtx-2070-super": "5394902600",
"rtx-2060-super": "5394903600",
"expensive-shirt": "5444021500"
},
"sv-se": {
"rtx-3090": "5438761600",
"rtx-3080": "5438798100",
"rtx-3070": null,
"titan-rtx": "5256301300",
"rtx-2080-super": "5336531300",
"rtx-2070-super": "5394902500",
"rtx-2060-super": "5394903900",
"expensive-shirt": "5444021500"
},
"da-dk": {
"rtx-3090": "5438793200",
"rtx-3080": "5438793300",
"rtx-3070": null,
"titan-rtx": "5256301800",
"rtx-2080-super": "5336531800",
"rtx-2070-super": "5394901800",
"rtx-2060-super": "5394903100",
"expensive-shirt": "5444021500"
},
"fr-be": {
"rtx-3090": "5438795600",
"rtx-3080": "5438795700",
"rtx-3070": null,
"titan-rtx": "5256301500",
"rtx-2080-super": "5336531500",
"rtx-2070-super": "5336534300",
"rtx-2060-super": "5394902700",
"expensive-shirt": "5444021500"
},
"de-at": {
"rtx-3090": "5444941400",
"rtx-3080": "5440853700",
"rtx-3070": null,
"titan-rtx": "5256301000",
"rtx-2080-super": "5335703700",
"rtx-2070-super": "5394901600",
"rtx-2060-super": "5394902900",
"expensive-shirt": "5444021500"
},
"cs-cz": {
"rtx-3090": "5438793600",
"rtx-3080": "5438793800",
"rtx-3070": null,
"titan-rtx": "5256301900",
"rtx-2080-super": "5336531900",
"rtx-2070-super": "5394901500",
"rtx-2060-super": "5394902800",
"expensive-shirt": "5444021500"
},
"fi-fi": {
"rtx-3090": "5438793200",
"rtx-3080": "5438793300",
"rtx-3070": null,
"titan-rtx": "5256301800",
"rtx-2080-super": "5336531800",
"rtx-2070-super": "5394901800",
"rtx-2060-super": "5394903100",
"expensive-shirt": "5444021500"
},
"nl-nl": {
"rtx-3090": "5438796600",
"rtx-3080": "5438796700",
"rtx-3070": null,
"titan-rtx": "5256302100",
"rtx-2080-super": "5336532100",
"rtx-2070-super": "5394902200",
"rtx-2060-super": "5394903500",
"expensive-shirt": "5444021500"
}
}

@Michael-Keen-MS
Copy link

Does anyone have a better way to check for stock? I was sending a get request to https://api-prod.nvidia.com/direct-sales-shop/DR/products/en_us/USD/5438481600 which would return a json response which would tell you inventory status, but now it doesn't work so well (error 503 - gateway times out).

Nvidia's own website makes the same website and now it fails there too, but eventually after a while the out of stock button pops up on their site. Do you guys think their website is setup so that if the request fails the out of stock button shows up? Or is their a better way to check for stock?

import requests

url = "https://api-prod.nvidia.com/direct-sales-shop/DR/products/en_us/USD/5438481600"

payload = {}
headers = {
  'authority': 'api-prod.nvidia.com',
  'accept': 'application/json, text/javascript, */*; q=0.01',
  'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36',
  'dnt': '1',
  'origin': 'https://www.nvidia.com',
  'sec-fetch-site': 'same-site',
  'sec-fetch-mode': 'cors',
  'sec-fetch-dest': 'empty',
  'referer': 'https://www.nvidia.com/en-us/geforce/graphics-cards/30-series/rtx-3090/',
  'accept-language': 'en-CA,en-GB;q=0.9,en-US;q=0.8,en;q=0.7'
}

response = requests.request("GET", url, headers=headers, data = payload)

print(response.text.encode('utf8'))

This should help:

from IPython.core.display import display, HTML
display(HTML("<style>.container { width:100% !important; }</style>"))

import requests
import json

payload = {}
headers = {
  'authority': 'api-prod.nvidia.com',
  'accept': 'application/json, text/javascript, */*; q=0.01',
  'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36',
  'dnt': '1',
  'origin': 'https://www.nvidia.com',
  'sec-fetch-site': 'same-site',
  'sec-fetch-mode': 'cors',
  'sec-fetch-dest': 'empty',
  'referer': 'https://www.nvidia.com/en-us/geforce/graphics-cards/30-series/rtx-3090/',
  'accept-language': 'en-CA,en-GB;q=0.9,en-US;q=0.8,en;q=0.7'
}

url = "https://api-prod.nvidia.com/direct-sales-shop/DR/products/en_us/USD/5438481700"

response = requests.request("GET", url, headers=headers, data = payload)

/* print(response.json()) -- you can use this to look at the full dict */

jsonResponse = response.json()

for url in jsonResponse["products"]["product"]:
    print(" PRODUCT NAME:   ", url["displayName"], '\n', "IN STOCK?:      ", url["inventoryStatus"]["productIsInStock"].upper(), '\n', "PRODUCT STATUS: ", url["inventoryStatus"]["status"], '\n', "PRICE:          ", url["pricing"]["formattedListPrice"])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment