Skip to the content.

Quick reference (TL;DR for agents)

Why no Python SDK?

Skool has no official API → no official SDK in any language. The Apify actor wraps Skool’s internal API behind a single HTTP endpoint. Calling it from Python is one requests.post(). Wrapping that in a small Python class gives you SDK-like ergonomics in ~30 lines.

Minimal client

import os
import requests

class SkoolClient:
    """Minimal Skool API client via the Apify-hosted actor."""

    BASE = "https://api.apify.com/v2/acts/cristiantala~skool-all-in-one-api/run-sync-get-dataset-items"

    def __init__(self, apify_token: str, cookies: str, group_slug: str):
        self.apify_token = apify_token
        self.cookies = cookies
        self.group_slug = group_slug

    def call(self, action: str, params: dict = None) -> dict:
        resp = requests.post(
            f"{self.BASE}?token={self.apify_token}&build=latest&timeout=90",
            json={
                "action": action,
                "cookies": self.cookies,
                "groupSlug": self.group_slug,
                "params": params or {},
            },
            timeout=120,
        )
        resp.raise_for_status()
        data = resp.json()
        # actor returns a list; first item is the result
        return data[0] if isinstance(data, list) and data else data

    # Convenience wrappers
    def list_pending(self):
        return self.call("members:pending")

    def approve(self, member_id: str):
        return self.call("members:approve", {"memberId": member_id})

    def post(self, title: str, content: str, label_id: str = None):
        params = {"title": title, "content": content}
        if label_id:
            params["labelId"] = label_id
        return self.call("posts:create", params)

    def reply_to_comment(self, post_id: str, comment_id: str, content: str):
        return self.call("posts:createComment", {
            "rootId": post_id,
            "parentId": comment_id,   # NOT postId — that publishes top-level instead of nested
            "content": content,
        })

# Usage
client = SkoolClient(
    apify_token=os.environ["APIFY_TOKEN"],
    cookies=os.environ["SKOOL_COOKIES"],
    group_slug="your-community",
)

# Approve pending members
pending = client.list_pending()
for m in pending.get("data", {}).get("members", []):
    client.approve(m["memberId"])

Bootstrap cookies — one-time

def login_and_save_cookies(email: str, password: str, group_slug: str, apify_token: str) -> str:
    resp = requests.post(
        f"https://api.apify.com/v2/acts/cristiantala~skool-all-in-one-api/run-sync-get-dataset-items?token={apify_token}&timeout=90",
        json={
            "action": "auth:login",
            "email": email,
            "password": password,
            "groupSlug": group_slug,
        },
        timeout=120,
    )
    data = resp.json()[0]
    if not data.get("success"):
        raise RuntimeError(f"auth:login failed: {data}")
    return data["cookies"]   # valid ~3.5 days

Save the returned cookies to disk, env var, or a vault. Reuse for ~3.5 days. Re-run when errorCode == "WAF_EXPIRED".

Async with httpx

import httpx, asyncio

class AsyncSkoolClient:
    def __init__(self, apify_token, cookies, group_slug):
        self.token = apify_token
        self.cookies = cookies
        self.group_slug = group_slug
        self._client = httpx.AsyncClient(timeout=120.0)

    async def call(self, action, params=None):
        resp = await self._client.post(
            f"https://api.apify.com/v2/acts/cristiantala~skool-all-in-one-api/run-sync-get-dataset-items?token={self.token}&build=latest&timeout=90",
            json={"action": action, "cookies": self.cookies, "groupSlug": self.group_slug, "params": params or {}}
        )
        data = resp.json()
        return data[0] if isinstance(data, list) and data else data

    async def close(self):
        await self._client.aclose()

# Run many actions in parallel (READS only — writes hit Skool's rate limit)
async def main():
    client = AsyncSkoolClient(os.environ["APIFY_TOKEN"], os.environ["SKOOL_COOKIES"], "your-community")
    courses, members, posts = await asyncio.gather(
        client.call("classroom:listCourses"),
        client.call("members:list"),
        client.call("posts:list", {"page": 1, "limit": 50}),
    )
    await client.close()

asyncio.run(main())

Auto-rotate cookies

class SkoolClient:
    # ... base class above ...

    def call_with_retry(self, action, params=None):
        result = self.call(action, params)
        if not result.get("success") and result.get("errorCode") == "WAF_EXPIRED":
            # cookies expired — rotate
            self.cookies = login_and_save_cookies(
                os.environ["SKOOL_EMAIL"],
                os.environ["SKOOL_PASSWORD"],
                self.group_slug,
                self.apify_token,
            )
            os.environ["SKOOL_COOKIES"] = self.cookies   # persist via your config layer
            return self.call(action, params)   # retry with fresh cookies
        return result

Using the Apify Python SDK

If you’re already using apify-client, the SDK is a thin wrapper around the same endpoint:

from apify_client import ApifyClient

client = ApifyClient(token=os.environ["APIFY_TOKEN"])

run = client.actor("cristiantala/skool-all-in-one-api").call(
    run_input={
        "action": "posts:create",
        "cookies": os.environ["SKOOL_COOKIES"],
        "groupSlug": "your-community",
        "params": {"title": "Hello from Python", "content": "First automated post."},
    },
    build="latest",
    timeout_secs=90,
)
# Fetch results from the run's default dataset
items = list(client.dataset(run["defaultDatasetId"]).iterate_items())
print(items[0])

The raw requests approach is slightly faster (no SDK overhead) and has fewer dependencies. The Apify SDK is convenient if you’re running other Apify actors in the same project.

Production patterns


Start using Skool from Python today

→ Open the Skool All-in-One API actor on Apify

No SDK to install. Just requests (or httpx, or apify-client). One POST per action. Pay-per-event (~$1.50/mo typical).

No Skool community yet? Launch one in 10 minutes — 14-day free trial.