Steam's Secret Weapon: Free Public APIs
Most platforms make you jump through hoops to access their data — API key applications, OAuth flows, rate limit tiers, developer agreements. Steam does none of that.
Steam exposes several public API endpoints that require zero authentication. No API keys. No tokens. No signup. Just send HTTP requests and get JSON back.
This makes Steam one of the easiest platforms to scrape programmatically, whether you're building a price tracker, a review aggregator, or a market research dashboard.
In this tutorial, I'll show you exactly how to use each endpoint with curl and Python examples, plus introduce an Apify actor that wraps everything into a single tool.
The Four Key Endpoints
1. Store Search API
Endpoint: https://store.steampowered.com/api/storesearch/?term=QUERY&l=english&cc=US
Search for games by keyword. Returns app IDs, names, prices, and thumbnails.
curl example:
curl -s "https://store.steampowered.com/api/storesearch/?term=survival&l=english&cc=US" | python3 -m json.tool
Python example:
import requests
response = requests.get(
"https://store.steampowered.com/api/storesearch/",
params={"term": "survival", "l": "english", "cc": "US"}
)
data = response.json()
for item in data.get("items", []):
price = item.get("price", {})
final = price.get("final", 0) / 100 if price else 0
print(f"{item['name']} - ${final:.2f}")
Sample output:
Rust - $39.99
Subnautica - $29.99
The Forest - $19.99
ARK: Survival Evolved - $29.99
2. App Details API
Endpoint: https://store.steampowered.com/api/appdetails?appids=APP_ID
Get comprehensive details for any game by its app ID. Returns descriptions, pricing, system requirements, Metacritic scores, screenshots, genres, categories, and more.
curl example:
# Get details for Counter-Strike 2 (app ID 730)
curl -s "https://store.steampowered.com/api/appdetails?appids=730" | python3 -m json.tool
Python example:
import requests
app_id = "730" # Counter-Strike 2
response = requests.get(
"https://store.steampowered.com/api/appdetails",
params={"appids": app_id}
)
data = response.json()
if data[app_id]["success"]:
game = data[app_id]["data"]
print(f"Name: {game['name']}")
print(f"Type: {game['type']}")
print(f"Description: {game['short_description'][:100]}...")
print(f"Developers: {', '.join(game.get('developers', []))}")
print(f"Genres: {', '.join(g['description'] for g in game.get('genres', []))}")
if "metacritic" in game:
print(f"Metacritic: {game['metacritic']['score']}")
if "price_overview" in game:
print(f"Price: {game['price_overview']['final_formatted']}")
else:
print("Price: Free to Play")
3. App Reviews API
Endpoint: https://store.steampowered.com/appreviews/APP_ID?json=1
Fetch user reviews with rich filtering options. You can filter by language, review type (positive/negative), purchase type, and date range.
curl example:
# Get recent English reviews for Baldur's Gate 3
curl -s "https://store.steampowered.com/appreviews/1086940?json=1&language=english&num_per_page=10&filter=recent" | python3 -m json.tool
Python example:
import requests
from datetime import datetime
app_id = "1086940" # Baldur's Gate 3
response = requests.get(
f"https://store.steampowered.com/appreviews/{app_id}",
params={
"json": 1,
"language": "english",
"num_per_page": 20,
"filter": "recent"
}
)
data = response.json()
summary = data.get("query_summary", {})
print(f"Total reviews: {summary.get('total_reviews', 'N/A')}")
print(f"Positive: {summary.get('total_positive', 'N/A')}")
print(f"Negative: {summary.get('total_negative', 'N/A')}")
print(f"Review score: {summary.get('review_score_desc', 'N/A')}")
print()
for review in data.get("reviews", [])[:5]:
vote = "👍" if review["voted_up"] else "👎"
hours = review["author"]["playtime_forever"] / 60
date = datetime.fromtimestamp(review["timestamp_created"]).strftime("%Y-%m-%d")
print(f"{vote} [{date}] {hours:.0f}h played")
print(f" {review['review'][:150]}...")
print()
4. Current Players API
Endpoint: https://api.steampowered.com/ISteamUserStats/GetNumberOfCurrentPlayers/v1/?appid=APP_ID
Get real-time concurrent player counts. Perfect for tracking game popularity over time.
curl example:
# Check current players for Dota 2
curl -s "https://api.steampowered.com/ISteamUserStats/GetNumberOfCurrentPlayers/v1/?appid=570" | python3 -m json.tool
Python example:
import requests
games = {
"730": "Counter-Strike 2",
"570": "Dota 2",
"1086940": "Baldur's Gate 3",
"292030": "The Witcher 3"
}
for app_id, name in games.items():
response = requests.get(
"https://api.steampowered.com/ISteamUserStats/GetNumberOfCurrentPlayers/v1/",
params={"appid": app_id}
)
data = response.json()
count = data.get("response", {}).get("player_count", 0)
print(f"{name}: {count:,} players online")
Rate Limits and Best Practices
Steam's API is generous but not unlimited. Here's what to keep in mind:
- Rate limit: Approximately 200 requests per 5 minutes per IP
- No authentication overhead: No tokens to refresh or manage
- JSON responses: Clean, well-structured data
- Tip: Add 0.5-1 second delays between requests to stay well within limits
import time
app_ids = ["730", "570", "440", "1086940", "292030"]
for app_id in app_ids:
response = requests.get(
"https://store.steampowered.com/api/appdetails",
params={"appids": app_id}
)
# Process response...
time.sleep(0.5) # Be a good citizen
Four Real-World Use Cases
1. Price Tracker
Monitor games on your wishlist and get notified when they go on sale:
def check_price(app_id, target_price):
resp = requests.get(
"https://store.steampowered.com/api/appdetails",
params={"appids": app_id}
)
data = resp.json()[str(app_id)]["data"]
price = data.get("price_overview", {})
current = price.get("final", 0) / 100
discount = price.get("discount_percent", 0)
if current <= target_price:
print(f"🔥 {data['name']} is ${current:.2f} ({discount}% off)!")
return current
2. Review Sentiment Analysis
Track how player sentiment changes over time — useful for gauging update reception:
def get_review_sentiment(app_id, days=30):
import time
day_start = int(time.time()) - (days * 86400)
resp = requests.get(
f"https://store.steampowered.com/appreviews/{app_id}",
params={
"json": 1, "language": "english",
"num_per_page": 100, "filter": "recent"
}
)
reviews = resp.json().get("reviews", [])
recent = [r for r in reviews if r["timestamp_created"] > day_start]
positive = sum(1 for r in recent if r["voted_up"])
return {
"total": len(recent),
"positive_pct": (positive / len(recent) * 100) if recent else 0
}
3. Competitor Research
Compare games in your genre across key metrics:
def compare_games(app_ids):
results = []
for app_id in app_ids:
details = requests.get(
"https://store.steampowered.com/api/appdetails",
params={"appids": app_id}
).json()[str(app_id)]["data"]
players = requests.get(
"https://api.steampowered.com/ISteamUserStats/GetNumberOfCurrentPlayers/v1/",
params={"appid": app_id}
).json()["response"]["player_count"]
results.append({
"name": details["name"],
"price": details.get("price_overview", {}).get("final_formatted", "Free"),
"metacritic": details.get("metacritic", {}).get("score", "N/A"),
"players_now": players
})
time.sleep(0.5)
return results
4. Market Research Dashboard
Combine search + details to analyze an entire genre:
def analyze_genre(keyword, max_games=20):
search = requests.get(
"https://store.steampowered.com/api/storesearch/",
params={"term": keyword, "l": "english", "cc": "US"}
).json()
prices = []
for item in search.get("items", [])[:max_games]:
price = item.get("price", {}).get("final", 0) / 100
if price > 0:
prices.append(price)
if prices:
print(f"Genre: {keyword}")
print(f"Games found: {len(prices)}")
print(f"Avg price: ${sum(prices)/len(prices):.2f}")
print(f"Price range: ${min(prices):.2f} - ${max(prices):.2f}")
The Easy Way: Use an Apify Actor
If you don't want to manage API calls, rate limiting, and data parsing yourself, there's an Apify actor that wraps all four endpoints into a single tool:
It handles:
- Game search by keyword
- Full game details extraction
- Review collection with filters
- Player count tracking
- Automatic rate limiting
- Clean JSON output
You can run it from the Apify console with zero code, schedule recurring runs, or integrate it via the Apify API into your own pipeline.
Conclusion
Steam's public API is remarkably developer-friendly — no keys, no auth, and generous rate limits. With just curl and basic Python, you can build powerful game data tools in minutes.
The four endpoints covered here (search, details, reviews, and players) cover the vast majority of use cases. For production workloads, consider using the Steam Scraper actor on Apify to handle the infrastructure for you.
Happy scraping!
All code examples use Steam's public API endpoints. No API keys required.
Top comments (0)