Scraping the Microsoft Store is underrated: its public endpoints expose data Apple and Google don't — 7-day and 30-day rating windows (momentum!), and customer reviews with helpful-vote counts and the reviewer's device family. No API key, no login, no headless browser. In this tutorial we'll fetch app details for any country market, search the catalog, and mine reviews — as clean structured JSON in a few lines of Python.
The endpoints
The Store client runs on two public JSON services:
# details (BATCHED — many apps in one call), any market/language
GET https://displaycatalog.mp.microsoft.com/v7.0/products?bigIds={id1},{id2}&market=US&languages=en-us&fieldsTemplate=Details
# search (the Store's real consumer search) and reviews
GET https://storeedgefd.dsx.mp.microsoft.com/v9.0/pages/searchResults?query=netflix&market=US&locale=en-US&...
GET https://storeedgefd.dsx.mp.microsoft.com/v9.0/ratings/product/{id}?market=US&locale=en-US&pageSize=25&skipItems=0
App IDs are the 12-character codes starting with 9 in every Store URL — apps.microsoft.com/detail/9NKSQGP7F2NH is WhatsApp. (Watch out: XP... IDs from winget are classic desktop installers, not Store products — the catalog 404s on them.)
You can call these yourself — but then you own the quirks: the $type-heavy search envelope, humanized rating counts ("332K"), the skipItems review pagination, the ID-format trap, and fixing it the day Microsoft shifts a payload. A cleaner path: one actor, one stable schema, canary-monitored daily. Here's how with the Microsoft Store Scraper.
Step 1 — Install the Apify client
pip install apify-client
export APIFY_TOKEN="apify_api_xxx"
Step 2 — App details with rating windows
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("freshactors/microsoft-store-scraper").call(run_input={
"mode": "details",
"productIds": ["9NKSQGP7F2NH", "9NCBCSZSJRSB", "9WZDNCRFJ3TJ"], # WhatsApp, Spotify, Netflix
})
for app in client.dataset(run["defaultDatasetId"]).iterate_items():
print(app["title"], app["rating"], app["rating30Days"])
A real record:
{
"productId": "9NKSQGP7F2NH",
"title": "WhatsApp",
"publisher": "WhatsApp Inc.",
"category": "Social",
"rating": { "average": 4.4, "count": 2294755 },
"rating7Days": { "average": 4.4, "count": 15549 },
"rating30Days": { "average": 4.4, "count": 68880 },
"price": { "amount": 0, "currency": "USD", "isFree": true },
"storeUrl": "https://apps.microsoft.com/detail/9NKSQGP7F2NH"
}
Comparing the windows to the all-time numbers tells you whether an app is improving or regressing right now — a signal the other stores simply don't publish. Want Germany instead? Add "market": "DE", "language": "de-de" and the descriptions, prices, and review pools localize.
Step 3 — Search the catalog
run = client.actor("freshactors/microsoft-store-scraper").call(run_input={
"mode": "search",
"searchTerms": ["pdf editor"],
"maxSearchResults": 10,
})
Each row carries the product ID, rating, price, categories, content rating, and IAP flag — ready for a details follow-up on the IDs you care about.
Step 4 — Reviews with helpful votes
run = client.actor("freshactors/microsoft-store-scraper").call(run_input={
"mode": "reviews",
"productIds": ["9NKSQGP7F2NH"],
"maxReviewsPerApp": 200,
})
Reviews paginate deep (WhatsApp has 55k+ on file) and each one includes helpfulPositive / helpfulNegative — i.e., community-validated complaints — plus deviceFamily and osVersion to split desktop vs Xbox feedback.
Pricing & reliability
Pay-per-result: app details $0.0025, search rows $0.001, reviews $0.0001 — no subscription, no per-run fee. A daily canary asserts the rating windows stay numeric, search coverage holds (Netflix must be findable), and review pagination advances — and we patch fast when Microsoft shifts an endpoint.
This completes the app-store set: same modes and schema family as our Apple App Store, Google Play, and VS Code Marketplace scrapers.
Questions or a field you're missing? Open an issue on the actor page — issues are answered fast.
Top comments (0)