# itch.io Games Scraper (`axiomworks/itchio-games-scraper`) Actor

Scrape public itch.io game listings and game pages for titles, developers, descriptions, platforms, tags, ratings, dates, and thumbnails. Browse top sellers, new and popular games, or other listings; fetching game-page details is optional.

- **URL**: https://apify.com/axiomworks/itchio-games-scraper.md
- **Developed by:** [Axiom Works](https://apify.com/axiomworks) (community)
- **Categories:** Games
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.98 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

**Returns:** one row per itch.io game with title, developer, developerUrl, platforms, genres, tags, and rating.
**Input:** `{"listing":"top-sellers","maxItems":10,"includeDetails":true}`
**Best for:** indie game discovery, genre research, and tracking public game listings.

```json
{"id": "785364", "sourceUrl": "https://adamgryu.itch.io/pumpkin-carver", "title": "The Annual Ghost Town Pumpkin Festival", "developer": "adamgryu", "platforms": ["Windows", "Linux", "macOS"], "rating": 4.9, "ratingCount": 458}
```

### What does itch.io Games Scraper do?

itch.io Games Scraper collects public game listings and game page details from itch.io. It can browse the site's top sellers, new and popular games, top rated games, and newest games. You can narrow a browse list by genre or tag, or give it an itch.io browse URL or a direct game URL. Each accepted game becomes one dataset row with a stable ID and the URL of its game page.

For direct game URLs, both Author and Authors rows are supported; `developer` and `developerUrl` identify the first listed creator.

The Actor uses the public HTML that a visitor can see without an account. Listing cards provide the title, creator, short description, displayed price tag, platforms, and thumbnail. When `includeDetails` is true, the Actor opens each game page to collect its rating, rating count, tags, genre, and dates if the creator has provided them. This makes it useful as an itch.io scraper or a structured itch.io API style feed for public discovery workflows. It does not claim affiliation with itch.io.

A single run stops at `maxItems`, so you can sample a category or request a larger list. Results are deduplicated by game ID within the run, including across listing pages. The Actor reports fields as they appear on the site; public listings can change order, availability, or metadata between runs. An empty result for a narrow filter may simply mean the current public listing has no matching cards.

### What data can you get?

The dataset schema includes every output field. A field can be null or an empty array when the page does not display that information. The table describes the value in each row, rather than promising that every game has every field.

| Field | What it contains |
| --- | --- |
| `id` | Stable itch.io game ID from the listing card or game page, with a URL-derived fallback. |
| `sourceUrl` | Public game page URL associated with the row. |
| `title` | Game title displayed on the listing or game page. |
| `developer` | Displayed creator or studio name. |
| `developerUrl` | Creator's public itch.io page URL. |
| `shortDescription` | Short listing text, when shown. |
| `price` | The listing's displayed price text, or null if the listing has no price tag. |
| `platforms` | Platform labels shown by the listing or game page. |
| `genres` | Genre labels from the listing or game information panel. |
| `tags` | Tags linked from the game information panel. |
| `rating` | Average rating displayed on the game page. |
| `ratingCount` | Count of ratings displayed on the game page. |
| `publishedAtIso` | `publishedAt` parsed to an ISO 8601 UTC timestamp, null when absent. |
| `updatedAtIso` | `updatedAt` parsed to an ISO 8601 UTC timestamp, null when absent. |
| `publishedAt` | Published or release date text if present on the game page. |
| `updatedAt` | Last update date text if present on the game page. |
| `thumbnailUrl` | Listing thumbnail image URL, when available. |
| `description` | Description text from the game page (up to 5000 characters), with spaces between paragraphs and list items; needs `includeDetails`. |
| `status` | Release status shown on the game page, such as Released. |
| `madeWith` | Tools or engines listed on the game page, when shown. |
| `languages` | Languages listed on the game page, when shown. |
| `inputs` | Input methods listed on the game page, when shown. |
| `averageSession` | Average session length shown on the game page, when shown. |

The overview table surfaces the fields most useful while scanning results: ID, game URL, title, creator, description, price, platforms, genres, tags, rating, rating count, and thumbnail. The downloadable dataset includes the remaining fields too. Use `sourceUrl` when you need to inspect a game's current public page, since descriptions, price displays, and ratings can change after the run.

For a platform-specific catalog, set `platform` to `linux` or another supported value. The Actor adds the platform constraint to the public browse URL alongside your genre and tag. For example, `{"listing":"top-sellers","platform":"linux","maxItems":10}` collects the Linux top-seller listing. Explicit URLs retain their own filters, and keyword searches use itch.io search rather than the generated browse filters.

The run stops before saving a result that exceeds your maximum cost per run. That stop gets a clear status message and preserves the records already saved. Retries distinguish visible challenge pages from ordinary pages that merely contain anti-bot scripts.

### How to use

Open the Actor input form, choose a listing, set `maxItems`, and run it. The default target is the public top sellers list. Set `includeDetails` to true when you need tags, ratings, or dates. Set it to false when listing card data is sufficient. A detail run sends an additional request for each game page, so its elapsed time grows with the number of rows.

To find games by keyword, put a term such as `roguelike` in `searchQuery`; the Actor reads the public itch.io search results the same way as a browse list. For a focused category, enter a slug such as `horror` in `tag` or `simulation` in `genre`. The Actor forms the corresponding public itch.io browse path. You may also paste a complete public browse URL into `startUrls`; this takes precedence over the listing and slug fields. Supplying a game page URL collects that game directly. Multiple start URLs are processed in the order given, while duplicate game IDs appear only once.

Use the `priceFilter` option to keep all games, listings without a price tag, or listings with a price tag. The filter uses the presence of a visible price tag, so a game with pay what you want behavior may require a closer look at its game page. If a game is unrated, `rating` and `ratingCount` remain null. If a creator did not set a distinct published date, `publishedAt` remains null. Empty arrays for tags or genres mean the corresponding labels were not found on the public page.

The Actor logs each target host it requests once. It makes requests at a modest pace and retries temporary blocks or server errors with backoff. The optional Apify Proxy control can be enabled for runs that need it. Public data is all it uses; no account login is required.

### Input

| Input field | Use |
| --- | --- |
| `startUrls` | Optional array of public itch.io browse or game URLs. It overrides generated listing URLs. |
| `listing` | Browse mode: `top-sellers`, `new-and-popular`, `top-rated`, or `newest`. Default `top-sellers`. |
| `searchQuery` | Optional keyword search on itch.io, for example `roguelike`. Used when `startUrls` is empty; it replaces the listing, genre and tag fields. |
| `genre` | Optional genre slug added to the generated browse path. |
| `tag` | Optional tag slug added to the generated browse path. |
| `platform` | Limit generated browse listings to `windows`, `osx`, `linux`, `android`, `ios`, or `web`; default empty means all. Ignored for explicit URLs and keyword search. |
| `priceFilter` | `any`, `free`, or `paid`; default `any`. |
| `maxItems` | Maximum unique result rows, from 1 through 10000; default 50. |
| `includeDetails` | Fetch game pages for extra fields; default true. |
| `proxyConfiguration` | Apify Proxy configuration; direct connections by default. |

For example, this input browses public new and popular horror games and keeps at most 30 distinct results:

```json
{
  "listing": "new-and-popular",
  "tag": "horror",
  "maxItems": 30,
  "includeDetails": true,
  "priceFilter": "any"
}
```

To use an exact URL instead, pass `{"startUrls":[{"url":"https://itch.io/games/top-sellers"}],"maxItems":40}`. You can also provide a direct game page URL under an `*.itch.io` subdomain. The Actor accepts HTTPS itch.io URLs and rejects unrelated hosts. Keep URL lists reasonably focused because every page is fetched at a polite pace. A browse URL without game cards returns no rows with a warning; a dead URL reports a clear error.

### Output

A run writes one dataset item per accepted game. This example is a real item from the local top sellers run; it shows a game with several populated detail fields and a missing published date:

```json
{
  "id": "785364",
  "sourceUrl": "https://adamgryu.itch.io/pumpkin-carver",
  "title": "The Annual Ghost Town Pumpkin Festival",
  "developer": "adamgryu",
  "developerUrl": "https://adamgryu.itch.io/",
  "shortDescription": "carve a lil pumpkin and share it with the world",
  "price": null,
  "platforms": [
    "Windows",
    "Linux",
    "macOS"
  ],
  "genres": [
    "Simulation",
    "Puzzle"
  ],
  "tags": [
    "Atmospheric",
    "Creative",
    "First-Person",
    "Ghosts",
    "Halloween",
    "Multiplayer",
    "pumpkins",
    "Short",
    "Spooky"
  ],
  "rating": 4.9,
  "ratingCount": 458,
  "publishedAt": null,
  "updatedAt": "02 October 2026 @ 14:35 UTC",
  "thumbnailUrl": "https://img.itch.zone/aW1nLzEzNTk4NTQ0LnBuZw==/315x250%23c/4CPM83.png"
}
```

Ratings, tag lists, and dates depend on what a game page exposes at run time. `includeDetails: false` still returns the listing fields and leaves detail-only fields empty. The exact order follows the site's current browse listing. The dataset API gives you JSON items for downstream tools, while the Store's table view is meant for scanning a run.

### How much does it cost?

This Actor is charged per result pushed to the dataset. Check the Actor's Pricing tab for the current terms before running it. `maxItems` is a strict upper bound on result records, and duplicate games in a run are not charged again. Requests that produce no accepted records do not create result charges. Setting `includeDetails` affects how many public pages the Actor requests and how long it runs, but it does not create a separate enrichment event.

For a small exploratory run, choose a low `maxItems` and inspect the first records. When the output matches your needs, raise the limit. The target site may reorder a browse list between runs, so the number of available rows can change. The Actor stops when a page has no game cards, when a listing repeats, or when the requested maximum has been reached.

### Use with AI agents (MCP)

Apify MCP lets an AI agent discover the Actor's input fields and call it as a tool. Configure an MCP client with the server URL below, then ask the agent for a concrete public game discovery task. The `tools` parameter selects this Store Actor:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?tools=axiomworks/itchio-games-scraper"
    }
  }
}
```

Example prompts: “Find 10 current top-selling itch.io games and show titles, developers, platforms, and ratings.” “Collect 20 new and popular games tagged horror, then group them by genre.” “Check the public page for this itch.io game and return its displayed creator, rating, tags, and update date.” Ask for only the fields you actually need in the agent's response, while retaining the full dataset for later analysis.

The Actor description and schema tell agents which arguments control the target, output size, and detail fetch. `startUrls` accepts complete public URLs, while `listing`, `genre`, and `tag` build a browse path. Agents should set `maxItems` deliberately so a broad request stays bounded. The returned `sourceUrl` gives an auditable link back to each public game page.

### Integrations and API

You can use the dataset in Apify integrations or call the Actor through the Apify API. Replace the Actor identifier and access token handling in your own environment as needed; keep tokens out of source files and logs. These examples show the input shape and how to retrieve result items. They are examples for a run you own, not a second source of game data.

Python with the Apify client:

```python
from apify_client import ApifyClient
import os

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("axiomworks/itchio-games-scraper").call(run_input={
    "listing": "top-sellers", "maxItems": 10, "includeDetails": True
})
items = list(client.dataset(run["defaultDatasetId"]).iterate_items())
```

JavaScript with the Apify client:

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('axiomworks/itchio-games-scraper').call({
  listing: 'top-sellers', maxItems: 10, includeDetails: true
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

A cURL call can start a run with the same JSON input:

```bash
curl -X POST \
  'https://api.apify.com/v2/acts/axiomworks~itchio-games-scraper/runs' \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"listing":"top-sellers","maxItems":10,"includeDetails":true}'
```

The run response identifies its default dataset. Fetch items from that dataset once the run succeeds. If you are building a recurring workflow, store each record's stable `id` and `sourceUrl` so you can compare successive public listings without confusing repeated games for new ones. A game's rating or tags can change, so decide whether your downstream system should preserve history or keep only the newest row.

### FAQ

**Why is a rating null?** A game without public ratings has no rating value to extract. With `includeDetails: false`, all rating fields stay null because game pages are not fetched.

**Why is a published date null?** Many game pages show an update date without a distinct published or release date. The Actor leaves `publishedAt` null rather than inventing a date.

**Can I scrape a single game?** Yes. Put the public game page URL in `startUrls`. A direct game page gives the game ID when the page provides one, with a stable URL-derived fallback.

**Can the same game appear twice?** A game may occur in more than one input listing, but the Actor keeps one row per observed game ID in a run. Separate runs each produce their own datasets.

**Why did a run return fewer than `maxItems`?** The requested page may have fewer public cards, a filter may exclude some cards, a later page may be empty, or a game card may lack the title and creator needed for a valid row. The Actor does not fill gaps with placeholder records.

### Is it legal to scrape itch.io?

This Actor reads public pages without logging in. The legality of a particular use depends on where you operate, what you collect, and what you do with the data. Review the site's current terms and applicable law for your use case. Respect creators' rights in game text and images, and use collected data responsibly. This Actor is independent and is not endorsed by itch.io.

### Feedback

If a selector stops matching the public site, share the input you used, the run ID, and which field appears incorrect. A public game URL and the expected visible text help reproduce a field issue. Do not include account credentials or private data. Feedback about listing filters, output fields, and documentation also helps keep this Actor useful as itch.io changes its public pages.

# Actor input Schema

## `startUrls` (type: `array`):

Optional itch.io URLs, one per object: a browse page like https://itch.io/games/top-sellers or https://itch.io/games/genre-horror, or a game page like https://adamgryu.itch.io/pumpkin-carver. Leave empty to use listing/searchQuery/genre/tag. maxItems is shared across all URLs; a dead or unreachable URL is skipped with a log warning.

## `listing` (type: `string`):

Which itch.io ranking to browse when startUrls and searchQuery are empty: top-sellers, new-and-popular, top-rated or newest. Default top-sellers. Combine with genre, tag, platform and priceFilter.

## `searchQuery` (type: `string`):

Keyword search on itch.io, e.g. 'roguelike' or 'pixel art platformer'. Used only when startUrls is empty; it replaces listing, genre, tag and platform. Leave empty to browse a listing. A term with no matches returns 0 items and a status message.

## `genre` (type: `string`):

Genre slug appended to the browse listing, e.g. 'simulation', 'puzzle' or 'rpg' (lowercase, hyphenated, as in itch.io genre URLs). Ignored when startUrls or searchQuery is set.

## `tag` (type: `string`):

Tag slug appended to the browse listing, e.g. 'horror' or 'pixel-art' (lowercase, hyphenated, as in itch.io tag URLs). Ignored when startUrls or searchQuery is set. Can be combined with genre.

## `priceFilter` (type: `string`):

Keep only 'free' games (no price tag), only 'paid' games, or 'any' (default). Applied after fetching, so a strict filter on a small listing may return fewer than maxItems.

## `maxItems` (type: `integer`):

Maximum game records across all URLs, 1-10000, default 50. Duplicate game IDs count once. Empty or blocked targets return no records and a status message.

## `includeDetails` (type: `boolean`):

true (default): open each game page for rating, ratingCount, tags, genres, dates, full description, status, tools, languages and inputs; slower. false: listing-card fields only (title, developer, price, platforms, thumbnail), much faster.

## `proxyConfiguration` (type: `object`):

Apify Proxy settings. Default is direct connections, which works for itch.io; enable Apify Proxy if requests get blocked (403/429), retries then use a fresh proxy session.

## `platform` (type: `string`):

Limit generated browse listings to a platform: windows, osx (macOS), linux, android, ios, or web (browser). Default empty returns all platforms. Ignored when startUrls or searchQuery is supplied.

## Actor input object example

```json
{
  "startUrls": [],
  "listing": "top-sellers",
  "searchQuery": "",
  "genre": "",
  "tag": "",
  "priceFilter": "any",
  "maxItems": 10,
  "includeDetails": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "platform": ""
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "listing": "top-sellers",
    "maxItems": 10,
    "includeDetails": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("axiomworks/itchio-games-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "listing": "top-sellers",
    "maxItems": 10,
    "includeDetails": True,
}

# Run the Actor and wait for it to finish
run = client.actor("axiomworks/itchio-games-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "listing": "top-sellers",
  "maxItems": 10,
  "includeDetails": true
}' |
apify call axiomworks/itchio-games-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,axiomworks/itchio-games-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/c1JPxIDdXQ40ofMxa/builds/mX5vmXq85oC9I43wn/openapi.json
