# Roblox Scraper - Games, Catalog, Users & Communities (`abotapi/roblox-scraper`) Actor

Scrape Roblox experiences, marketplace items, users and communities. Player counts, visits, likes, genre, creator, resale prices and price history, limited status, follower counts, community members and roles. Search, ids or pasted links, with incremental change tracking for scheduled runs.

- **URL**: https://apify.com/abotapi/roblox-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** Automation, Other
- **Features:** Limited permissions
- **Stats:** 23 total users, 5 monthly users, 95.2% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 records

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

## Roblox Scraper: Experiences, Marketplace, Players & Communities

Roblox Scraper turns Roblox into a clean, flat JSON feed. Get experiences with their live player counts, visits, likes and creator, marketplace items with resale prices and price history, game passes, player profiles with follower and connection counts, and communities with their roles and full member rosters. Give it a keyword, an id, or paste links, and it works out what each one is. Built-in incremental mode makes it a monitoring tool as well as a one-off extractor, and results can also be piped into your own apps.

### Why This Scraper?

- **Five sources, one dataset.** Experiences, marketplace items, game passes, players and communities all return through the same dataset with a `kind` column, instead of five separate tools.
- **Deep experience data.** Live player count, total visits, favourites, likes and dislikes with a derived like ratio, plus, with detail on, sampled live server stats, media counts and badges.
- **Marketplace depth on demand.** Resale price, recent average price, up to 30 points of price history and total quantity for limited items.
- **Six link shapes accepted as-is.** Paste an experience, marketplace item, bundle, game pass, profile or community link, or a discover or catalog listing page, and the actor works out what each one is.
- **Incremental change tracking built in.** Records are compared run over run and classified NEW, UPDATED, UNCHANGED or EXPIRED, with the exact fields that moved.
- **Detail lookups protect the rest of the run.** If the extra per-record lookups start coming back empty for many records in a row, they turn themselves off for the rest of that run, so the base records still come back.
- **Honest failure.** A refused run fails loudly instead of returning an empty dataset, and Resume continues one interrupted pull without paying twice for rows already collected.

### Use Cases

- **Player count and trend monitoring:** track live players, visits and favourites for a watchlist of experiences over time.
- **Limited item and resale tracking:** watch marketplace collectibles for price, quantity and resale history changes.
- **Community research:** pull a community's member roster, roles and rank breakdown.
- **Creator and catalog research:** compare genres, creators, prices and player counts across many experiences or marketplace items at once.
- **Player lookups:** resolve usernames or profile links to follower, following and connection counts.

### Data You Get

> Sample shape, values are illustrative placeholders, not from a live record.

The table below shows an experience record (`kind: "game"`), the most detailed of the six kinds this actor returns.

| Field | Example |
| --- | --- |
| `kind` | `"game"` (also `"catalogItem"`, `"gamePass"`, `"user"`, `"group"`, `"groupMember"`) |
| `recordId` | `game-1` |
| `id` / `universeId` | `1` |
| `rootPlaceId` | `2` |
| `url` | `https://www.roblox.com/games/2/Sample-Experience` |
| `name` | `Sample Experience` |
| `description` | `Full experience description text.` |
| `creatorName` / `creatorType` | `Sample Studio` / `Group` |
| `genre` / `genreL1` / `genreL2` | `All` / `RPG` / `Action RPG` |
| `playing` | `1000` |
| `visits` | `10000000` |
| `maxPlayers` | `20` |
| `favoritedCount` | `500000` |
| `upVotes` / `downVotes` / `likeRatio` | `900000` / `100000` / `0.9` |
| `createdAt` / `updatedAt` | `2020-01-01T00:00:00.000Z` / `2026-01-01T00:00:00.000Z` |
| `iconUrl` | `https://tr.rbxcdn.com/00000000/512/512/Image/Png` |
| `sampledServerCount` / `sampledServerPlayers` | `100` / `1200` (when detail is on) |
| `avgServerFps` / `avgServerPing` | `59.5` / `150.0` (when detail is on) |
| `mediaImageCount` / `mediaVideoCount` | `5` / `1` (when detail is on) |
| `badges` | `[{ "id": 0, "name": "Sample Badge", "awardedCount": 1000 }]` (when detail is on) |
| `scrapedAt` | `2026-01-02T00:00:00.000Z` |
| `changeType` / `changedFields` | `"UPDATED"` / `["favoritedCount", "visits"]` (incremental mode only) |

Marketplace item rows (`kind: "catalogItem"`) carry `itemType` (Asset or Bundle), `categoryName`, `price`, `lowestPrice`, `lowestResalePrice`, `itemRestrictions`, `isLimited`, `isLimitedUnique`, `hasResellers` and `thumbnailUrl`, plus `recentAveragePrice`, `salesCount` and `priceHistory` for single assets when Fetch full details is on (bundles are never enriched). Game pass rows (`kind: "gamePass"`, only reachable by pasting a game pass link in URL mode) carry `price`, `productId`, `creatorId`, `creatorName`, `creatorType`, `creatorHasVerifiedBadge`, `isForSale`, `createdAt`, `updatedAt` and `iconImageAssetId`. User rows (`kind: "user"`) carry `displayName`, `hasVerifiedBadge`, `friendsCount`, `followersCount`, `followingCount`, `robloxBadges`, `createdExperiencesCount` and `avatarHeadshotUrl`. Community rows (`kind: "group"`) carry `memberCount`, `ownerUsername`, `publicEntryAllowed`, `shoutBody`, `roleCount`, `roles` and `groupExperiences`, and community member rows (`kind: "groupMember"`) carry `groupName`, `roleName` and `roleRank` for one member per row.

### How to Use

1. Pick a mode: `games` (experiences, keyword or id), `catalog` (marketplace search), `users` (usernames, ids or a directory search), `groups` (communities, optionally with every member) or `url` (paste roblox.com links; each is routed by shape).
2. Fill in the search fields for that mode. The filter and sort fields below apply no matter which mode you picked.
3. Set Max items to control run size and cost, then click Start.
4. Download the dataset as JSON, CSV or Excel, or read it through the API.

**Search experiences by keyword:**

```json
{
  "mode": "games",
  "gameQueries": ["tycoon", "obby"],
  "minPlaying": 500,
  "maxItems": 100
}
```

**Paste a mix of links:**

```json
{
  "mode": "url",
  "urls": [
    "https://www.roblox.com/games/2753915549/Blox-Fruits",
    "https://www.roblox.com/catalog/1365767/Valkyrie-Helm",
    "https://www.roblox.com/users/156/profile"
  ],
  "maxItems": 50
}
```

#### URL mode: supported link shapes

Leaving `urls` untouched in URL mode now scrapes one sample link of each shape below (previously it ran nothing). An unrecognised link is skipped with a warning in the run log.

| Shape | Example |
|---|---|
| Experience keyword search | `https://www.roblox.com/discover?Keyword=obby` |
| Experience, with slug | `https://www.roblox.com/games/920587237/Adopt-Me` |
| Experience, id only | `https://www.roblox.com/games/2753915549` |
| Marketplace keyword listing | `https://www.roblox.com/catalog?Keyword=dominus` |
| Marketplace listing, filtered and sorted (`Category`, `salesTypeFilter`, `SortType` are honoured) | `https://www.roblox.com/catalog?Category=11&Keyword=hat&salesTypeFilter=2&SortType=3` |
| Marketplace item | `https://www.roblox.com/catalog/1028606/Red-Baseball-Cap` |
| Bundle | `https://www.roblox.com/bundles/1/Man` |
| User profile | `https://www.roblox.com/users/156/profile` |
| User, id only | `https://www.roblox.com/users/1` |
| Community, legacy path | `https://www.roblox.com/groups/7/Roblox-Fan-Group` |
| Community | `https://www.roblox.com/communities/1200769/x` |

Game pass links (`/game-pass/<id>`) are still parsed but are not part of the samples.

**Track limited items and their resale prices:**

```json
{
  "mode": "catalog",
  "catalogCategory": "accessories",
  "catalogSalesType": "collectibles",
  "catalogSortType": "priceHighToLow",
  "minPrice": 1000,
  "maxItems": 200
}
```

**Monitor the same search daily and get only the changes:**

```json
{
  "mode": "catalog",
  "catalogSalesType": "collectibles",
  "incrementalMode": true,
  "stateKey": "limiteds-watch",
  "emitExpired": true,
  "maxItems": 0
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/roblox-scraper").call(run_input={"mode": "games", "gameQueries": ["tycoon"], "maxItems": 50})
for record in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(record["name"], record["playing"], record["visits"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/roblox-scraper').call({ mode: 'games', gameQueries: ['tycoon'], maxItems: 50 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

#### Resume and recurring updates

- **Resume** (`resumeFromRunId`) continues one interrupted run: paste its run or dataset id and the actor skips every record id it already returned there, so you don't pay twice.
- **Incremental mode** (`incrementalMode`) is for scheduled runs over the same search. Each record is classified `NEW`, `UPDATED` (with `changedFields`), `UNCHANGED` (suppressed and not billed unless `emitUnchanged` is on), or `EXPIRED`, only after a run that scanned the whole tracked search end to end, was not capped by Max items, was not a Resume, and had no refused requests, and only with `emitExpired` on. `REAPPEARED` is not a normal outcome of running the same search twice: it only appears for a record that a previous complete scan already marked `EXPIRED`, and that later turns up again. Prices, off-sale status and stock are treated as real changes; the marketplace fields `mainImage`, `itemCreatedUtc`, `quantityLimitPerUser`, `itemStatus`, `bundledItems`, `isRecolorable` and `isFreeItem` are returned but not compared, so a change in only those fields does not mark a record `UPDATED` (price, which `isFreeItem` follows, lowest price, off-sale status and stock are compared); the live player count, visits, favourites, member and follower counts, the sampled live server stats and the scrape time are excluded from change detection because they move constantly, though they are still returned with their current value. Use `ignoreFieldsForChanges` to exclude more fields (dotted paths reach nested fields); changing that list never marks records as updated. Three optional controls shape marketplace monitoring, all off by default: `changeScope` set to price and stock narrows marketplace items to price, lowest price, off-sale status and remaining stock, `compactUpdates` trims an `UPDATED` row to its identity fields, the changed fields and the change details, and `expireAfterMissedScans` waits for several complete scans in a row before a record is marked `EXPIRED`. `changeScope` and `expireAfterMissedScans` never change what is billed for a delivered row; with `compactUpdates` on, a compacted `UPDATED` row is billed the detail-enrichment event only when one of its changed fields came from the extra detail lookups (every delivered row is still billed the dataset-item event). `stateKey` names or shares the stored state; leave it empty and the actor derives one from the mode and search, so different searches never mix state.
- Combining Resume with Incremental mode is only allowed the first time a state key is used. Once that state key has tracked records from an earlier run, the run fails with a message asking you to drop Resume or pick a different State key.

#### Filters and sorts

- **Experiences:** `minPlaying` keeps only experiences with at least that many players right now.
- **Marketplace:** `catalogSalesType`, `catalogSortType`, `catalogCreatorName` and `catalogIncludeUnavailable` apply to every marketplace search unless the pasted listing link carries its own `salesTypeFilter`, `SortType`, `CreatorName` or `includeNotForSale`, in which case the link's value is used. `catalogCategory` and `catalogKeyword` are superseded by a pasted listing link (the link carries its own `Category` and `Keyword`). `minPrice` and `maxPrice` always apply, including to a pasted listing link.
- Marketplace rows also carry `mainImage`, `itemCreatedUtc`, `quantityLimitPerUser`, `itemStatus`, `bundledItems`, `isRecolorable` and `isFreeItem`; these are extra output columns and are not part of change detection.

#### Output views

The dataset has these views: Results (all kinds together), Experiences, Marketplace, Users and communities, and Changes (incremental). The Output tab links each one, plus a run summary saved as the `OUTPUT` record.

#### How Max items is shared across multiple searches

When a run has more than one search target, several game queries, several user ids, and so on, the Max items budget is divided evenly across them, so one heavily-populated query does not use up the whole budget before the others are read.

### Send results into your apps (MCP connectors)

Results can optionally be piped into the apps you already use through Model Context Protocol connectors. This is an extra delivery step after the scrape; the Apify dataset itself is never changed.

Authorize a connector once under Apify, Settings, Integrations (Notion, Linear, Airtable or Apify), then select it in the `mcpConnectors` input field. For Notion, also set `notionParentPageUrl` to the page under which item pages should be created; other connectors receive a best-effort write.

The connector receives a condensed, human-readable summary per item: a title plus the key fields flattened to plain text, with nested objects collapsed to their main value and arrays trimmed to a few names. The complete record always stays in the Apify dataset, and selecting a connector never changes the dataset output. `maxNotifyListings` caps how many items are sent to each connector per run; it does not affect the dataset.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | select | `games` | `games`, `catalog`, `users`, `groups` or `url`. The search fields of the other modes are ignored; the filter and sort fields below apply whichever mode you run. |
| `gameQueries` | array | `["blox fruits"]` | Keywords, experience ids, place ids or experience links. One search per entry. |
| `catalogKeyword` | string | none | Free-text marketplace search. Superseded by a pasted marketplace listing link, which carries its own keyword. |
| `catalogCategory` | select | `all` | `all`, `accessories`, `clothing`, `avatarAnimations` or `heads`. Superseded by a pasted marketplace listing link, which carries its own category. |
| `userQueries` | array | `["builderman"]` | Usernames, user ids or profile links. The sample username `builderman` is ignored when `userKeyword` (Directory search) is filled in, so a keyword-only search does not also return the sample user; any other list you enter is always used. |
| `userKeyword` | string | none | Search the player directory for this text and return every matching profile. |
| `groupQueries` | array | `["7"]` | Community names, ids or community links. A plain name is looked up with the public community search and must match a community name exactly (ignoring case); otherwise the entry is skipped with a warning that lists close matches, and the run fails with a clear message when no entry resolves. A link to anything other than a community is skipped with a warning. |
| `fetchGroupMembers` | boolean | `false` | Also return one row per community member with their role and rank. |
| `urls` | array | one sample link per supported shape (see the URL table above) | Roblox links for URL mode. Leaving the field untouched now scrapes the sample links instead of failing; clear the list and paste your own. |
| `minPlaying` | integer | none | Keep only experiences with at least this many players in game right now. Applies to every experience row, including one returned by a pasted link. |
| `catalogSalesType` | select | `any` | `any`, `collectibles` (limited and resellable), `limited` or `premium`. Applies to every marketplace search; if a pasted marketplace listing link carries its own `salesTypeFilter`, the link's value is used instead. |
| `catalogSortType` | select | `relevance` | `relevance`, `favorited`, `priceLowToHigh`, `priceHighToLow`, `bestselling` or `recentlyPublished`. Applies to every marketplace search; if a pasted marketplace listing link carries its own `SortType`, the link's value is used instead. |
| `catalogCreatorName` | string | none | Only marketplace items made by this creator (user or group name). Applies to every marketplace search; if a pasted marketplace listing link carries its own `CreatorName`, the link's value is used instead. |
| `catalogIncludeUnavailable` | boolean | `false` | Also return marketplace items that are not currently for sale. A pasted marketplace listing link that carries its own `includeNotForSale` uses the link's value. |
| `minPrice` | integer | none | Robux price floor for marketplace items. Applies to every marketplace search, including one built from a pasted marketplace listing link. |
| `maxPrice` | integer | none | Robux price ceiling for marketplace items. Applies to every marketplace search, including one built from a pasted marketplace listing link. |
| `fetchDetails` | boolean | `true` | Add the extra per-record data. Billed as a detail-enrichment surcharge, only for records that receive it and are actually delivered. |
| `maxPages` | integer | `0` | Result pages per search target. `0` means read until the source runs out. |
| `maxItems` | integer | `20` | Total records across all searches. `0` means up to 1,000,000 records, which is also the maximum accepted value. |
| `resumeFromRunId` | string | none | Continue a previous run or dataset without repeating rows already collected. |
| `incrementalMode` | boolean | `false` | Return only what changed since the last run of the same search. |
| `stateKey` | string | none | Name an incremental monitoring campaign. |
| `emitUnchanged` | boolean | `false` | Also return, and bill, records that did not change. |
| `emitExpired` | boolean | `false` | Also return, and bill, records that are no longer found, only after a complete scan. |
| `changeScope` | select | `all` | Incremental mode only. `all` compares every field except the built-in excluded ones and your own ignore list. `priceStock` narrows marketplace items to price, lowest price, off-sale status and remaining stock, so other edits do not mark an item `UPDATED`; other record kinds are unaffected. A narrowed scope keeps its own stored baseline. |
| `compactUpdates` | boolean | `false` | Incremental mode only. An `UPDATED` row carries only its identity fields, the current value of each changed field and the change details; `NEW` rows stay complete. Billing: every delivered row is billed the dataset-item event as before; a compacted `UPDATED` row is billed the detail-enrichment event only when one of its changed fields came from the extra detail lookups. |
| `expireAfterMissedScans` | integer | `0` | Incremental mode with `emitExpired` only. `0` marks a record `EXPIRED` after the first complete scan that does not find it; `2` or more waits for that many complete scans in a row (maximum 30). |
| `ignoreFieldsForChanges` | array | none | Fields left out of change detection (incremental mode only), added to the built-in exclusions (the constantly moving counters and the extra marketplace output columns listed in the Incremental mode section); dotted paths for nested fields. |
| `proxy` | object | Apify proxy | Connection settings. The default Apify proxy connection is used; see Plan Requirement below. |
| `mcpConnectors` | array | none | Optional MCP connectors to also receive the results. |
| `notionParentPageUrl` | string | none | Notion page under which item pages are created. |
| `maxNotifyListings` | integer | `50` | Cap on items sent to each connector. Does not affect the dataset. |

### Output Example

> Sample shape, values are illustrative placeholders, not from a live record.

```json
{
  "kind": "game",
  "recordId": "game-1",
  "id": 1,
  "universeId": 1,
  "rootPlaceId": 2,
  "url": "https://www.roblox.com/games/2/Sample-Experience",
  "name": "Sample Experience",
  "description": "Full experience description text.",
  "creatorId": 3,
  "creatorName": "Sample Studio",
  "creatorType": "Group",
  "creatorHasVerifiedBadge": true,
  "genre": "All",
  "genreL1": "RPG",
  "genreL2": "Action RPG",
  "price": null,
  "playing": 1000,
  "visits": 10000000,
  "maxPlayers": 20,
  "favoritedCount": 500000,
  "upVotes": 900000,
  "downVotes": 100000,
  "likeRatio": 0.9,
  "createdAt": "2020-01-01T00:00:00.000Z",
  "updatedAt": "2026-01-01T00:00:00.000Z",
  "copyingAllowed": false,
  "createVipServersAllowed": true,
  "universeAvatarType": "MorphToR15",
  "isContentRestricted": false,
  "iconUrl": "https://tr.rbxcdn.com/00000000/512/512/Image/Png",
  "sampledServerCount": 100,
  "sampledServerPlayers": 1200,
  "avgServerFps": 59.5,
  "avgServerPing": 150.0,
  "mediaImageCount": 5,
  "mediaVideoCount": 1,
  "badges": [
    { "id": 0, "name": "Sample Badge", "awardedCount": 1000, "winRatePercentage": 0.1 }
  ],
  "changeType": "UPDATED",
  "changedFields": ["favoritedCount", "visits"],
  "firstSeenAt": "2026-01-01T00:00:00.000Z",
  "lastSeenAt": "2026-01-02T00:00:00.000Z",
  "scrapedAt": "2026-01-02T00:00:00.000Z"
}
```

### Plan Requirement

The actor needs an Apify account with proxy access. Measured against Roblox, a datacenter connection returns real pages and data, so residential proxies are not required, and the actor never selects a premium proxy group for you. The proxy is billed to your own Apify plan. If the default connection is refused for your account, the run switches to a built-in backup datacenter connection and logs: "Served over the backup connection (the default connection was unavailable)." On a plan without residential proxies it also warns that residential access needs an upgrade. If no page can be read, the run fails with one of these messages instead of an empty dataset: "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required" (also check the credentials of any proxy URLs you entered); "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Roblox pages"; or "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search." Each request has a 25 second deadline. Game pass links (`/game-pass/<id>`) are currently not served as pages by Roblox, so they may return nothing. No other credential or subscription is required.

### FAQ

#### How much does it cost?

Three events are charged: a one-time charge when the run starts, one dataset-item charge per record pushed to the dataset, and one detail-enrichment charge per record whose full details were fetched and that is delivered to the dataset, when Fetch full details is on. A record suppressed as UNCHANGED never carries this extra charge, even if its details were fetched, and a compacted `UPDATED` row (Compact updated rows) carries it only when a changed field it ships came from the detail lookups. The Pricing tab shows the current rates. Use Max items to cap the cost of any run.

#### Is it legal to scrape Roblox?

This actor reads the same public JSON endpoints Roblox's own pages call, without any credential. You are responsible for how you use the data: follow Roblox's terms and the laws that apply to you, and get legal advice before any commercial redistribution. Usernames, profile text and creator names can be personal data in some jurisdictions, so handle them accordingly.

#### Can I get only new or changed data on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Unchanged records are not returned or billed unless you turn on Emit unchanged, and Emit expired records only produces tombstones for items that vanished, and only after a run that scanned the tracked search completely.

#### Why did I never see a REAPPEARED record?

REAPPEARED is not a normal outcome of running the same search twice. It only appears for a record that a previous complete scan, with Emit expired records on, not capped, not resumed, nothing refused, already marked EXPIRED, and that later turns up again in a further run. If you have never turned on Emit expired records, or no run has ever scanned its whole tracked search end to end, REAPPEARED will never appear, and that is expected.

#### Why did my run fail instead of returning an empty dataset?

If every request to Roblox's endpoints is refused, the run stops with a clear message so "no matches for this search" is never confused with "nothing could be read". Re-run in a few minutes. A run also fails if the selected mode's required search field is empty, or if Resume is combined with Incremental mode on a state key that already has tracked records from an earlier run.

#### Why are some fields empty even though Fetch full details is on?

Game passes, community members and marketplace bundles are always returned complete from their listing page and never carry the extra detail fields, and are never charged the surcharge. For experiences, marketplace items, players and communities, if the extra lookups come back empty for many records in a row, they turn off for the rest of that run and the base fields still come back. The sampled live server numbers describe up to 100 currently running public servers, not every server of the experience.

#### Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push a summary of each record into Notion, Linear or Airtable.

### 🔗 More scrapers you might like

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>🧩 <a href="https://apify.com/abotapi/ok-ru-scraper"><b>OK.ru Scraper</b></a><br>Scrape public OK.ru users, groups, topics, posts, videos, games and greetings by keyword...</td><td>🛒 <a href="https://apify.com/abotapi/itch-io-scraper"><b>itch.io Game, Review, Creator and Jam Scraper</b></a><br>Scrape itch.io games by genre, tag, platform, price band or keyword, plus creator...</td></tr>
<tr><td>🧩 <a href="https://apify.com/abotapi/pikabu-scraper"><b>Pikabu Scraper</b></a><br>Scrape Pikabu (Пикабу): keyword search, hot/new/best feeds, communities, tags, full story...</td><td>🧩 <a href="https://apify.com/abotapi/crazygames-scraper"><b>CrazyGames Scraper</b></a><br>Scrape CrazyGames games with ratings, upvotes and downvotes, total plays and likes...</td></tr>
<tr><td>🧩 <a href="https://apify.com/abotapi/tiktok-comments-scraper"><b>TikTok Comments Scraper</b></a><br>Scrape comments from TikTok videos using one or more video URLs or IDs. Extract comment...</td><td>👗 <a href="https://apify.com/abotapi/snkrdunk-com-scraper"><b>SNKRDUNK Scraper</b></a><br>Scrape SNKRDUNK (snkrdunk.com), Japan's sneaker and streetwear resale marketplace: JP and...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/roblox-scraper/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <contact@abotapi.com>.
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

## `mode` (type: `string`):

games = search or look up experiences. catalog = search the avatar marketplace. users = look up or search players. groups = look up communities and, optionally, their members. url = paste roblox.com links and let the scraper work out what each one is.

## `gameQueries` (type: `array`):

One entry per search. Each entry can be a keyword ("tycoon", "blox fruits"), a numeric experience or place id, or a roblox.com experience link. Keywords are searched, ids and links are looked up directly.

## `catalogKeyword` (type: `string`):

Optional free-text search, for example "dominus", "valkyrie", "headphones". Leave blank to browse the chosen category.

## `catalogCategory` (type: `string`):

Which slice of the marketplace to browse. Only these categories are served to a signed-out request. A pasted listing link carries its own category.

## `userQueries` (type: `array`):

One entry per user. Each entry can be a username, a numeric user id, or a roblox.com profile link. Usernames are resolved to ids automatically. The sample username is ignored when Username search is filled in.

## `userKeyword` (type: `string`):

Optional. Search the player directory for this text and return every matching profile, not just the first page of matches.

## `groupQueries` (type: `array`):

One entry per community (group). Each entry can be a community name, a numeric community id or a roblox.com community link. A plain name is looked up with the public community search and must match a community name exactly (ignoring case); otherwise the entry is skipped with a warning in the log that lists close matches, and the run fails if no entry resolves. A link to anything other than a community is skipped with a warning.

## `fetchGroupMembers` (type: `boolean`):

Return one extra row per member (username, display name, role and rank) alongside the community record. Large communities have millions of members, so keep Max items set unless you really want the whole roster.

## `urls` (type: `array`):

One or more roblox.com links. Supported: experience pages (/games/...), marketplace items (/catalog/...), bundles (/bundles/...), game passes (/game-pass/...), user profiles (/users/.../profile), communities (/groups/... or /communities/...), and the listing pages /discover?Keyword=... and /catalog?Keyword=... which return their whole result set. Multi-link supported. The search fields of the other modes are ignored, with one exception: the Filters and sort fields below still apply, so a player floor drops experiences returned by these links and the marketplace controls shape a pasted /catalog?Keyword=... listing search (a sale type, sort order, creator or off-sale flag written in the link itself wins over the matching field).

## `minPlaying` (type: `integer`):

Only keep experiences with at least this many players in-game at the moment the run reads them. Leave empty to keep every result. It applies to every experience the run returns, whether it came from an Experiences search or from a pasted experience or /discover link.

## `catalogSalesType` (type: `string`):

Narrow to a sale type. Collectibles are the limited and limited-unique items that can be resold, and they are the ones that carry resale prices and price history. It applies to every marketplace search, unless a pasted /catalog?Keyword=... listing link carries its own salesTypeFilter, in which case the link's value is used.

## `catalogSortType` (type: `string`):

How the marketplace orders the results before they are returned. It applies to every marketplace search, unless a pasted /catalog?Keyword=... listing link carries its own SortType, in which case the link's value is used.

## `catalogCreatorName` (type: `string`):

Only marketplace items made by this creator (user or group name). Leave empty for any creator. It applies to every marketplace search, unless a pasted /catalog?Keyword=... listing link carries its own CreatorName, in which case the link's value is used.

## `catalogIncludeUnavailable` (type: `boolean`):

Also return marketplace items that are not currently for sale. It applies to every marketplace search, unless a pasted /catalog?Keyword=... listing link carries its own includeNotForSale, in which case the link's value is used.

## `minPrice` (type: `integer`):

Only return marketplace items priced at or above this. Leave empty for no floor. It applies to every marketplace search, whether built from the Marketplace catalog fields above or from a pasted /catalog?Keyword=... listing link.

## `maxPrice` (type: `integer`):

Only return marketplace items priced at or below this. Leave empty for no ceiling. It applies to every marketplace search, whether built from the Marketplace catalog fields above or from a pasted /catalog?Keyword=... listing link.

## `fetchDetails` (type: `boolean`):

Add the extra per-record data: live server statistics, media counts and badges for experiences; resale price, sales and price history for marketplace items; connection, follower and following counts plus created experiences for users; roles and community experiences for communities. Adds extra requests per record and is billed as a detail-enrichment surcharge. Turn off for a lighter run that returns only the base fields. Community members, game passes and bundles are always returned complete and are never charged the surcharge.

## `maxPages` (type: `integer`):

How many result pages to read per search target. 0 (default) means unlimited: reading stops naturally once the source reports no further page, or sooner once Max items is reached. Set a number only for an explicit page cap below that natural stop.

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

The sole soft cap on the run: stop after this many records across all searches. Defaults to 20 so a run stays small unless you raise it. 0 = up to the maximum of 1,000,000 records (or the natural end of each listing). Larger values are lowered to 1,000,000.

## `proxy` (type: `object`):

The source limits how many requests a single address may make in a short window, so a proxy is what keeps a larger run moving. The default works on every Apify plan, including the free one, and no premium group is ever selected for you.

## `resumeFromRunId` (type: `string`):

Paste a previous run ID or dataset ID to continue a large pull without returning or charging for records already collected there. Use this after an interrupted run. For recurring monitoring of the same search, use Incremental mode below instead.

## `incrementalMode` (type: `boolean`):

Turn this on for daily or recurring monitoring. The first run returns everything as NEW. Later runs normally return only NEW, UPDATED and REAPPEARED records. Values that move on their own between runs (live player count, visits, favourites, member and follower counts, sampled live server statistics, scrape time) are excluded from change detection, so a record whose only difference is one of them counts as unchanged; those fields are still returned with their current value. Prices, off-sale status and stock are compared. The marketplace fields mainImage, itemCreatedUtc, quantityLimitPerUser, itemStatus, bundledItems, isRecolorable and isFreeItem are returned but not compared, so a change in only those fields does not mark a record UPDATED (price, which isFreeItem follows, lowest price, off-sale status and stock are compared). You can exclude more fields with the ignore setting below. State is kept separately for each mode, search and detail setting; use State key to name or deliberately share a campaign.

## `stateKey` (type: `string`):

Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key from the mode, search and detail settings, so different searches never mix state.

## `emitUnchanged` (type: `boolean`):

Off by default. Turn on to also return records that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have, so leave it off unless you want the full snapshot every run.

## `emitExpired` (type: `boolean`):

Off by default. Turn on to also return records that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search: not when Max items capped it, not when Resume was used, and not when any request was refused. This returns, and bills, extra rows.

## `changeScope` (type: `string`):

All fields (default) compares every field except the built-in excluded ones and your own ignore list. Price and stock only narrows marketplace items to price, lowest price, off-sale status and remaining stock, so other edits (description, favourites) no longer mark an item UPDATED. Other record kinds are unaffected. A narrowed scope keeps its own stored baseline.

## `compactUpdates` (type: `boolean`):

Off by default. When on, an UPDATED row carries only its identity fields, the current value of each changed field and the change details. NEW rows stay complete. A compacted UPDATED row is billed the detail-enrichment event only when a changed field it carries came from the extra detail lookups.

## `expireAfterMissedScans` (type: `integer`):

0 (default) marks a record EXPIRED after the first complete scan that does not find it. Set 2 or more to wait for that many complete scans in a row before marking it EXPIRED. Only applies with Emit expired records on.

## `ignoreFieldsForChanges` (type: `array`):

Optional, incremental mode only. Field names to leave out when deciding whether a record changed, for example likeRatio or creator.name. Dotted paths reach nested fields and apply to every item of a list. The fields are still returned; they are just not compared and never appear in changedFields. Changing this list does not mark records as updated.

## `mcpConnectors` (type: `array`):

Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify, Settings, Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title plus key fields), not the full JSON; the complete record always stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "games",
  "gameQueries": [
    "blox fruits"
  ],
  "catalogCategory": "all",
  "userQueries": [
    "builderman"
  ],
  "groupQueries": [
    "7"
  ],
  "fetchGroupMembers": false,
  "urls": [
    "https://www.roblox.com/discover?Keyword=obby",
    "https://www.roblox.com/games/920587237/Adopt-Me",
    "https://web.roblox.com/games/2753915549",
    "https://www.roblox.com/catalog?Keyword=dominus",
    "https://www.roblox.com/catalog?Category=11&Keyword=hat&salesTypeFilter=2&SortType=3",
    "https://www.roblox.com/catalog/browse.aspx?CatalogContext=1&Keyword=cap",
    "https://www.roblox.com/catalog/1028606/Red-Baseball-Cap",
    "https://www.roblox.com/bundles/1/Man",
    "https://www.roblox.com/users/156/profile",
    "https://www.roblox.com/users/1",
    "https://www.roblox.com/user.aspx?id=2",
    "https://www.roblox.com/groups/7/Roblox-Fan-Group",
    "https://www.roblox.com/communities/1200769/x",
    "https://www.roblox.com/groups/group.aspx?gid=1"
  ],
  "catalogSalesType": "any",
  "catalogSortType": "relevance",
  "catalogIncludeUnavailable": false,
  "fetchDetails": true,
  "maxPages": 0,
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "changeScope": "all",
  "compactUpdates": false,
  "expireAfterMissedScans": 0,
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `experiences` (type: `string`):

No description

## `marketplace` (type: `string`):

No description

## `people` (type: `string`):

No description

## `changes` (type: `string`):

No description

## `summary` (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 = {
    "mode": "games",
    "gameQueries": [
        "blox fruits"
    ],
    "catalogCategory": "all",
    "userQueries": [
        "builderman"
    ],
    "groupQueries": [
        "7"
    ],
    "fetchGroupMembers": false,
    "urls": [
        "https://www.roblox.com/discover?Keyword=obby",
        "https://www.roblox.com/games/920587237/Adopt-Me",
        "https://web.roblox.com/games/2753915549",
        "https://www.roblox.com/catalog?Keyword=dominus",
        "https://www.roblox.com/catalog?Category=11&Keyword=hat&salesTypeFilter=2&SortType=3",
        "https://www.roblox.com/catalog/browse.aspx?CatalogContext=1&Keyword=cap",
        "https://www.roblox.com/catalog/1028606/Red-Baseball-Cap",
        "https://www.roblox.com/bundles/1/Man",
        "https://www.roblox.com/users/156/profile",
        "https://www.roblox.com/users/1",
        "https://www.roblox.com/user.aspx?id=2",
        "https://www.roblox.com/groups/7/Roblox-Fan-Group",
        "https://www.roblox.com/communities/1200769/x",
        "https://www.roblox.com/groups/group.aspx?gid=1"
    ],
    "catalogSalesType": "any",
    "catalogSortType": "relevance",
    "catalogIncludeUnavailable": false,
    "fetchDetails": true,
    "maxPages": 0,
    "maxItems": 20,
    "proxy": {
        "useApifyProxy": true
    },
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "changeScope": "all",
    "compactUpdates": false,
    "expireAfterMissedScans": 0
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/roblox-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 = {
    "mode": "games",
    "gameQueries": ["blox fruits"],
    "catalogCategory": "all",
    "userQueries": ["builderman"],
    "groupQueries": ["7"],
    "fetchGroupMembers": False,
    "urls": [
        "https://www.roblox.com/discover?Keyword=obby",
        "https://www.roblox.com/games/920587237/Adopt-Me",
        "https://web.roblox.com/games/2753915549",
        "https://www.roblox.com/catalog?Keyword=dominus",
        "https://www.roblox.com/catalog?Category=11&Keyword=hat&salesTypeFilter=2&SortType=3",
        "https://www.roblox.com/catalog/browse.aspx?CatalogContext=1&Keyword=cap",
        "https://www.roblox.com/catalog/1028606/Red-Baseball-Cap",
        "https://www.roblox.com/bundles/1/Man",
        "https://www.roblox.com/users/156/profile",
        "https://www.roblox.com/users/1",
        "https://www.roblox.com/user.aspx?id=2",
        "https://www.roblox.com/groups/7/Roblox-Fan-Group",
        "https://www.roblox.com/communities/1200769/x",
        "https://www.roblox.com/groups/group.aspx?gid=1",
    ],
    "catalogSalesType": "any",
    "catalogSortType": "relevance",
    "catalogIncludeUnavailable": False,
    "fetchDetails": True,
    "maxPages": 0,
    "maxItems": 20,
    "proxy": { "useApifyProxy": True },
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "changeScope": "all",
    "compactUpdates": False,
    "expireAfterMissedScans": 0,
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/roblox-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 '{
  "mode": "games",
  "gameQueries": [
    "blox fruits"
  ],
  "catalogCategory": "all",
  "userQueries": [
    "builderman"
  ],
  "groupQueries": [
    "7"
  ],
  "fetchGroupMembers": false,
  "urls": [
    "https://www.roblox.com/discover?Keyword=obby",
    "https://www.roblox.com/games/920587237/Adopt-Me",
    "https://web.roblox.com/games/2753915549",
    "https://www.roblox.com/catalog?Keyword=dominus",
    "https://www.roblox.com/catalog?Category=11&Keyword=hat&salesTypeFilter=2&SortType=3",
    "https://www.roblox.com/catalog/browse.aspx?CatalogContext=1&Keyword=cap",
    "https://www.roblox.com/catalog/1028606/Red-Baseball-Cap",
    "https://www.roblox.com/bundles/1/Man",
    "https://www.roblox.com/users/156/profile",
    "https://www.roblox.com/users/1",
    "https://www.roblox.com/user.aspx?id=2",
    "https://www.roblox.com/groups/7/Roblox-Fan-Group",
    "https://www.roblox.com/communities/1200769/x",
    "https://www.roblox.com/groups/group.aspx?gid=1"
  ],
  "catalogSalesType": "any",
  "catalogSortType": "relevance",
  "catalogIncludeUnavailable": false,
  "fetchDetails": true,
  "maxPages": 0,
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "changeScope": "all",
  "compactUpdates": false,
  "expireAfterMissedScans": 0
}' |
apify call abotapi/roblox-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/roblox-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/CLeS2VDy89n05tgRe/builds/Tq0rZRH0L83Zifu8a/openapi.json
