Scrape product prices and stock status as typed JSON
A scrape product prices API has one job: give you a number you can compare, not a string with a currency symbol glued to it. Price monitoring, competitor tracking, marketplace feeds and affiliate catalogs all need the current price and whether the item is in stock, from stores that never agreed on a markup. The Scraping API reads both with a few typed rules per store.
Every store formats the same price differently
One shop prints £51.77, another 51,77 € with a strikethrough list price next to it, a third renders the price after the page loads. The value you want is in there, but it arrives as text in a different element on every domain, and the stock status is a sentence rather than a flag.
A regular expression per store works until the template changes, and parseFloat on the wrong element silently records the old price or the shipping fee. Stores that render prices in the browser return nothing to a plain HTTP fetch, and larger retailers put antibot protection in front of the product pages you care about most.
Extraction rules make the price a typed field. type: 'number' returns a number, an array of rules tries structured markup first and the visible label second, and waitForSelector holds the extraction until a client-rendered price exists. The type reference lists every validator.
How to extract a price from a product URL
Start with the visible price, then harden the rule with fallbacks. Each store gets its own small rule set, and the result has the same shape for all of them.
import createClient from 'microlink.io'
const microlink = createClient({
apiKey: process.env.MICROLINK_API_KEY
})
const { price, stock } = await microlink.extract(
'https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html',
{
price: { selector: '.product_main .price_color', attr: 'text', type: 'number' },
stock: { selector: '.product_main .availability', attr: 'text' }
}
)On this demo store price comes back as 51.77 and stock as the label In stock (22 available). Turning that label into a boolean is one comparison on your side.
import createClient from 'microlink.io'
const microlink = createClient({
apiKey: process.env.MICROLINK_API_KEY
})
const rules = {
price: [
{ selector: '[itemprop=price]', attr: 'content', type: 'number' },
{ selector: '.price-now', attr: 'text', type: 'number' },
{ selector: '.price', attr: 'text', type: 'number' }
],
currency: { selector: '[itemprop=priceCurrency]', attr: 'content' }
}
const { price, currency } = await microlink.extract(url, rules)The rules run in order and the first one that yields a valid number wins, so structured microdata is preferred and the visible label is the safety net. The currency travels as its own field.
import createClient from 'microlink.io'
const microlink = createClient({
apiKey: process.env.MICROLINK_API_KEY
})
const { price } = await microlink.extract(
url,
{ price: { selector: '.price', attr: 'text', type: 'number' } },
{ prerender: true, waitForSelector: '.price', ttl: '1h' }
)prerender forces a browser, waitForSelector waits for the price element, and ttl keeps the result cached for an hour so repeated checks within that window are served from cache.
- type number returns a numeric price. A value that is not a valid number becomes null.
- selector The first element matching the price selector. Scope it to the main product block.
- waitForSelector Waits for the price element on stores that render it in the browser.
- prerender auto by default. Set true when the price is missing from the initial HTML.
- ttl How long a price stays cached, from 1 minute to 31 days. Pro plans.
- proxy.location Two-letter country code for stores that show a different price per country. Pro plans.
There is no scheduler on the Microlink side: run the calls from your own job at the interval you need and compare the numbers there. When the price already sits in Open Graph product tags and you also want the title and image, extract custom fields alongside metadata returns everything in one response.
Why typed rules make a sturdier ecommerce price scraper
A price monitor fails quietly: the job keeps running and stores the wrong value. Types and fallbacks turn those quiet failures into nulls you can see.
Lists of products use the same rules nested under selectorAll, see scrape tables and repeated lists for category pages.
The data extraction troubleshooting guide covers null fields, wrong selectors and pages that were not ready yet.
When not to: if the price only appears after choosing a size or color, a single rule reads the default variant. Click the option inside a remote Puppeteer function and read the price there.
FAQ
How do I scrape a product price as a number?
Can an ecommerce price scraper keep the currency?
How do I scrape prices from stores that render with JavaScript?
How often can I re-check a scraped product price?
What happens when a store blocks my price scraper?
Solve the next problem with the same API
Any website to JSON
Custom fields from JavaScript apps
Tables and lists to JSON arrays
Custom fields alongside metadata
Screenshot a site from another country
Link previews for bot-protected sites
Ready to track prices as numbers?
Typed prices and stock from any product URL. Start on the free tier and write the rules for your first store today.