# Skool Community Finder (`dami_studio/skool-discovery-scraper`) Actor

Search Skool for communities by keyword, category, price, language or private/public, and get one row each: url, name, members, price, description. Finds communities you have no links for.

- **URL**: https://apify.com/dami\_studio/skool-discovery-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Lead generation, Social media, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.80 / 1,000 community founds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Skool Community Finder

Search Skool and get back the communities, as rows.

Type a keyword, or pick a category and a price, and this returns one row per community: the URL, the
name, how many members it has, what it costs, what it says about itself, whether it is private or
public, and when it was created. No links needed. That is the point of it.

### The awkward part first

**Skool stops handing out results at 1,000 per search.** Page 34 is the last one with anything on it.
That is Skool's ceiling, not a setting here, and no amount of paging gets past it. If you want more
than a thousand communities you need more than one search: several keywords, or a sweep across the
nine categories, which is why the search box takes a list rather than a single word.

**Sorting does nothing while you are searching.** Set a keyword and an order together and Skool
returns the same rows in the same order either way. The run drops the order and tells you it did,
rather than leaving a control on screen that quietly does nothing. Order works when you browse a
category without a keyword.

**Private and public are two separate lists.** Skool's discovery page shows private communities by
default, and the public ones sit in a list it never mixes in. Neither list is a subset of the other:
they share nothing. If you only ever browse the default view you have been looking at half of Skool.

### How it relates to the other Skool Actor

This publisher ships a second Skool Actor, **Skool Community Scraper** (`skool-group-scraper`), and
the two do opposite jobs:

| | Skool Community Finder (this one) | Skool Community Scraper |
|---|---|---|
| What you give it | a keyword, or a category and a price | a list of community links |
| What it does | searches Skool for communities you have no link for | reads communities you already know about |
| What comes back | the listing record: url, name, members, price, description | the full about page: owner, rating, review count, admin/post/course counts |

The natural order is this one first, then feed its `communityUrl` column into the other. This Actor
deliberately stops at what the search listing carries. It does not open every community it finds,
because opening 1,000 about pages to enrich a list you are still filtering is a bill nobody asked
for.

### What you put in

```json
{
  "searchTerms": ["ai automation", "n8n", "make.com"],
  "price": "paid",
  "maxItems": 300
}
```

Or browse instead of searching:

```json
{
  "category": "money",
  "price": "free",
  "communityType": "public",
  "sortBy": "top",
  "maxItems": 500
}
```

| Field | What it does |
|---|---|
| `searchTerms` | Up to 20 keywords, one per line. Each is searched separately and the results merged, so a community that matches three of them is returned once. |
| `category` | One of Skool's nine: hobbies, music, money, spirituality, tech, health, sports, self-improvement, relationships. |
| `price` | `free`, `paid`, or `free-trial`. |
| `communityType` | `private` or `public`. See above: they are different lists. |
| `language` | One of the 48 languages Skool tags communities with. |
| `sortBy` | `trending` or `top`. Browsing only. |
| `maxItems` | How many communities to return in total. This is your cost ceiling. |

Leave everything empty and you get a single free sample row showing the output shape, and nothing is
charged beyond the start fee.

**A value Skool does not recognise stops the run before it makes a single request.** That is
deliberate and it is worth knowing why: a misspelled category is not rejected by Skool, it is
answered with an empty page. Passing it through would show you "no communities found" for a category
that is actually full. So the run refuses it up front and names the nine that exist.

### What comes back

```json
{
  "communityUrl": "https://www.skool.com/makerschool",
  "slug": "makerschool",
  "name": "Maker School",
  "description": "Learn to build software products with AI. Weekly live builds.",
  "memberCount": 12400,
  "isPaid": true,
  "priceLabel": "$97/month",
  "priceAmount": 97,
  "priceCurrency": "USD",
  "priceInterval": "month",
  "monthlyPriceAmount": 97,
  "annualPriceAmount": null,
  "oneTimePriceAmount": null,
  "isPublic": false,
  "category": "tech",
  "language": null,
  "matchedTerm": "ai automation",
  "discoveryRank": 3,
  "discoveryPage": 1,
  "logoUrl": "https://assets.skool.com/f/…/logo.jpg",
  "coverImageUrl": "https://assets.skool.com/f/…/cover-md.jpg",
  "brandColor": "#1B5EF5",
  "groupId": "c6c02cc8a1264ebebe527f744c50ebe9",
  "createdAt": "2023-04-11T09:12:03.410000Z",
  "updatedAt": "2026-09-20T16:43:04.888821Z",
  "scrapedAt": "2026-09-20T19:44:02.118Z"
}
```

How often each field is actually there, counted over 540 communities pulled across six different
searches:

| Field | Present |
|---|---|
| name, description, memberCount, brandColor | 540 of 540 |
| coverImageUrl | 538 of 540 |
| logoUrl | 536 of 540 |
| a price of some kind, on paid communities | 331 of 540. The rest are free, and carry no price at all |

`priceInterval` is `month`, `year` or `one_time`. A community with no price is `isPaid: false` and
`priceLabel: "Free"`, read off the record rather than guessed from the filter you used.

`category` and `language` are filled in only when you filtered by them. The listing row itself
carries neither, so writing anything there on an unfiltered search would be inventing it.

### Does the filtering actually filter?

Worth asking, because plenty of search APIs accept a filter, ignore it, and hand back everything.
These were each checked by running the same search with and without the filter and comparing the
communities that came back:

- **Category is a clean split.** All nine compared against each other, 36 pairs, and not one
  community appeared in two categories. Still true at page 1, page 10 and page 34.
- **Price holds.** 180 communities pulled under "free", and every one had no price. 180 under "paid",
  every one had a price.
- **Private and public share nothing.** 30 each, zero overlap.
- **Language moves the list.** Spanish shares 3 of 30 with the default; German shares none.
- **Keywords match the text.** The word appeared in the name, slug or description of 89 of the 90
  communities checked.

Two of those (price and private/public) leave a mark on the row itself, so every row is checked
against them before you are billed. Anything that comes back not matching is dropped and not
charged. Category, language and free-trial leave nothing on the row to check against, so those are
Skool's answer passed through. The table above is the evidence for them, not a promise that a second
check happens.

### What this does not do

- **It does not go past 1,000 results for one search.** Skool's limit.
- **It does not open the communities it finds.** No owner name, no email, no rating, no review
  count, no post or course counts. Those live on the about page, which the companion Actor reads.
- **It does not collect people.** No member lists, no reviews, no profiles, no emails. The search
  listing carries none of that and nothing here goes looking for it.
- **It does not log in.** Everything here is what a signed-out visitor sees, so anything Skool hides
  from the public is hidden from this too.
- **It cannot tell you which category an unfiltered result belongs to.** Skool does not put the
  category on the row. Filter by one and the answer is known; otherwise the field is empty.
- **It does not verify the free-trial filter.** Skool has no trial marker on the row to check.
- **It does not sort search results.** Skool ignores order while searching. Browse instead.

### What it costs you

**$2.80 per 1,000 communities**, plus a **$0.00015 start fee per run**. Flat on every plan, with no
volume tiers, no minimum, no subscription. You are billed once per community returned, and
nothing else bills:

- the sample row an empty run gives you: free
- a search Skool has nothing for: free, and it costs one request to find out
- a refused filter value: free, and zero requests
- a community dropped for not matching your filters: free
- any run that fails, times out or gets refused: free

So a search that finds nothing costs you $0.00015 and nothing more. A 45-community run is about
13 cents; a full 1,000-community sweep of one category is $2.80.

### Speed

A 45-community run takes 2 requests and about 3 seconds. Skool serves 30 communities per page, so
the request count is roughly `maxItems / 30` plus one. A full 1,000-community sweep of one category
is 34 requests.

### FAQ

**Can I search Skool without an account?**
Yes. This reads Skool's public discovery listing. No login, no cookie, no API key.

**How do I find every community in a category?**
Set `category`, leave `searchTerms` empty, and set `maxItems` to 1000. That is the whole category as
far as Skool will hand it over.

**How do I find free Skool communities?**
Set `price` to `free`. Add a category or a keyword to narrow it.

**Why do I get different communities than I see on skool.com?**
Most likely you are looking at the default view, which is private communities. Set `communityType`
to `public` to see the other list.

**Can I get the owner's email or the community's rating?**
Not from this one. The search listing does not carry them. Run the companion Skool Community
Scraper over the `communityUrl` column for that.

**Why did my run return nothing?**
Either Skool genuinely has nothing for that search, in which case the dataset holds a row saying so,
or a filter value was not one Skool recognises, in which case the row names the values that are. Both
are free.

**Is the member count live?**
It is what Skool's listing said at the moment of the run, and `scrapedAt` records when that was.

**How many communities can I get in one run?**
Up to 5,000, but no single search goes past 1,000, so reaching the higher numbers means several
search terms or several categories.

# Actor input Schema

## `searchTerms` (type: `array`):

What to search Skool for. One term per line, up to 20. Each term is searched on its own and the results are merged, so a community that matches two terms is returned once and billed once. Matching is close to a plain text match on the community name, slug and description rather than anything clever, so 'ai automation' and 'automation' give quite different lists. Leave this empty to browse a category instead.

## `category` (type: `string`):

Skool's own nine categories. Picking one is a real split, not a nudge: the nine category listings share no communities at all. Leave on Any to search across everything.

## `price` (type: `string`):

Free, paid, or communities running a free trial. Free and paid are checked against every row before it is billed — a paid community coming back from a free search is dropped and not charged. Free trial is passed through as Skool answers it, because the listing carries no trial marker to check against.

## `communityType` (type: `string`):

Skool's discovery page shows private communities by default, and public ones are a separate list it never mixes in. Pick Public to search that second list. Checked against every row before it is billed.

## `language` (type: `string`):

The language the community runs in, as Skool tags it. The listing carries no language field on the row, so this is Skool's own answer passed through rather than something checked here.

## `sortBy` (type: `string`):

Only applies when you are browsing without search terms. Skool ignores the order while a search is running, so if you set both, this is dropped and the run says so rather than pretending it did something.

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

How many communities to return, across all search terms. You are billed per community returned, so this is your cost ceiling. Skool itself stops at 1,000 results for any single search, so going past that needs more than one search term.

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

Optional. Leave this alone unless you need the run to go out through a particular network. Your own proxy servers are used exactly as given.

## Actor input object example

```json
{
  "searchTerms": [
    "ai automation"
  ],
  "category": "any",
  "price": "any",
  "communityType": "any",
  "language": "any",
  "sortBy": "trending",
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Every row in the default dataset: communityUrl, slug, name, description, memberCount, isPaid, priceLabel, priceAmount, priceCurrency, priceInterval, monthlyPriceAmount, annualPriceAmount, oneTimePriceAmount, isPublic, category, language, matchedTerm, discoveryRank, discoveryPage, logoUrl, coverImageUrl, brandColor, groupId, createdAt, updatedAt, scrapedAt. A run with no search term, a refused filter value, a search Skool has nothing for, or a refusal returns a single uncharged row explaining what happened instead.

# 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 = {
    "searchTerms": [
        "ai automation"
    ],
    "category": "any",
    "price": "any",
    "communityType": "any",
    "language": "any",
    "sortBy": "trending",
    "maxItems": 100,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/skool-discovery-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 = {
    "searchTerms": ["ai automation"],
    "category": "any",
    "price": "any",
    "communityType": "any",
    "language": "any",
    "sortBy": "trending",
    "maxItems": 100,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/skool-discovery-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 '{
  "searchTerms": [
    "ai automation"
  ],
  "category": "any",
  "price": "any",
  "communityType": "any",
  "language": "any",
  "sortBy": "trending",
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call dami_studio/skool-discovery-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/skool-discovery-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/EkjD6eytRQuCh9XPc/builds/T7hrfx5xwEPxUA02O/openapi.json
