# Ghost Explore Scraper (`aurenic/ghost-explore-scraper`) Actor

Scrape the Ghost Explore newsletter directory: publications, member counts, revenue signals and staff contacts. Keyless, HTTP-only, no login.

- **URL**: https://apify.com/aurenic/ghost-explore-scraper.md
- **Developed by:** [Aurenic](https://apify.com/aurenic) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 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.

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

## Ghost Explore Scraper

Scrape the Ghost Explore newsletter directory: publications, member counts, revenue signals and staff contacts — keyless, HTTP-only, no login.

### What does Ghost Explore Scraper do?

Ghost Explore (`explore.ghost.org`) is the first-party discovery directory that Ghost runs for publications built on its platform. Every listing carries a complete structured payload embedded in the page as HTML `data-*` attributes: publication name, description, external newsletter URL, icon, accent color, subscriber count, staff roster with social links, owner testimonial with revenue figures, and ActivityPub handle. No API key, no login, no JavaScript rendering.

This actor reads that payload, plus the public per-site RSS JSON endpoint, and returns one row per publication per ranking page.

### Output fields

| Field | Type | Description |
|---|---|---|
| slug | string | Ghost Explore identifier, e.g. `tangle` |
| name | string | Publication display name |
| description | string | Publication description |
| newsletter_url | string | External newsletter URL (with `?ref=ghost-explore`) |
| profile_url | string | Ghost Explore profile page URL |
| icon_url | string | Publication logo |
| accent_color | string | Brand accent color (hex) |
| member_count | integer | Subscriber count when published publicly |
| show_members | boolean | Whether the publication displays its member count |
| is_top_100 | boolean | Whether the publication is in Ghost Explore's top 100 |
| ap_handle | string | ActivityPub / social web handle |
| ap_follower_count | integer | ActivityPub follower count |
| ap_following_count | integer | ActivityPub following count |
| staff_users | array | Staff roster with name, role, posts, bio, profile image, Twitter, LinkedIn, Instagram, YouTube, TikTok, Mastodon, Bluesky, Threads, Facebook, website |
| staff_count | integer | Number of staff listed |
| testimonial | object | Owner quote with revenue and subscriber signals |
| category | string | Category or ranking page that produced this row |
| ranking_list | string | Source page slug |
| rank | integer | Position on the source page (1-based) |
| source_page_url | string | URL of the source page |
| rss_posts | array | Recent posts (when `includeRssPosts` is on): title, url, published_at, author, image |
| latest_post_date | string | Most recent post date (when RSS is on) |
| scraped_at | string | ISO timestamp |

### Who is it for?

- **Sponsorship sales** prospecting Ghost newsletters by category, reach and revenue signal
- **PR and media relations** building writer contact lists from the staff roster
- **Market research** ranking the Ghost newsletter ecosystem by subscriber count
- **Competitive intelligence** tracking which publications enter the Top 100 and Trending lists
- **CRM enrichment** auto-filling publication contacts and social links
- **AI agents and MCP users** pulling structured creator data for analysis

### Pricing

**Pay per result: $1.00 per 1,000 publications.**

Charged only for records actually written to the dataset.

### How to use it

1. Open the actor in Apify Console.
2. Choose the **categories and ranking pages** to crawl. Defaults to the four main ranking pages: Top Members, Top Revenue, Trending, Recent.
3. Optionally set a language filter.
4. Optionally turn on **Include recent RSS posts** to attach the most recent posts per publication.
5. Click **Start** and export as JSON, CSV or Excel.

### Output example

```json
{
  "record_type": "ghost_explore_publication",
  "slug": "tangle",
  "name": "Tangle",
  "description": "Summarizing the best arguments from across the political spectrum. 100% independent, subscriber-supported, and non-partisan.",
  "newsletter_url": "https://www.readtangle.com",
  "profile_url": "https://explore.ghost.org/p/tangle",
  "icon_url": "https://fls-9e7c60dc-a2b4-4b4b-872e-862c515a14da.laravel.cloud/icons/af03a256-3922-42d6-bb76-fc3bcdabf330-0fc9be73.webp",
  "accent_color": "#951867",
  "member_count": 881000,
  "show_members": true,
  "is_top_100": true,
  "ap_handle": null,
  "staff_users": [
    {
      "name": "Isaac Saul",
      "role": "Owner",
      "posts": 2307,
      "bio": "I'm a politics reporter who grew up in Bucks County, PA...",
      "twitter": "https://twitter.com/Ike_Saul",
      "linkedin": null,
      "website": null
    }
  ],
  "staff_count": 5,
  "testimonial": {
    "quote": "It has now been one year since I quit my full-time job to go all in on Tangle. Today, we have [75,000] paying subscribers. That's roughly [$4M] in gross yearly revenue",
    "author": "Isaac Saul"
  },
  "category": "top-members",
  "ranking_list": "top-members",
  "rank": 1,
  "source_page_url": "https://explore.ghost.org/top-members",
  "rss_posts": null,
  "scraped_at": "2026-10-03T12:00:00.000Z"
}
```

### Technical details

- **Stack:** Node.js 24, `apify` SDK, native `fetch`, `cheerio`.
- **Source:** `https://explore.ghost.org/{category}` — server-rendered HTML. No JavaScript execution required.
- **Extraction:** each publication is an `<a data-site-slug="...">` anchor carrying the full payload as `data-*` attributes. `data-staff-users` and `data-testimonial` are HTML-entity-encoded JSON objects, decoded automatically by cheerio.
- **RSS enrichment:** `https://explore.ghost.org/api/sites/{slug}/rss` returns a JSON array of recent posts. Optional.
- **Categories:** ranking pages (`top`, `top-members`, `top-revenue`, `trending`, `recent`, `social-web`, `personal`) plus 30+ topic pages (`tech`, `business`, `programming`, `news`, `finance`, `culture`, `travel`, `education`, `art`, `faith-spirituality`, `health`, `literature`, `sport`, `entertainment`, `productivity`, `design`, `food-drink`, `music`, `crypto`, `science`, `fiction`, `gaming`, `nature-outdoors`, `house-home`, `fashion-beauty`, `podcasts`, `gear-gadgets`, `history`, `parenting`, `climate`, `youtubers`).
- **Language filter:** query string `?lang=en` (supports en, fr, es, de, it, pt, ja, pl, nl, ko).
- **Retries:** 429 and 5xx responses are retried up to three times with backoff.
- **Proxy:** defaults to the Apify datacenter pool.

### Known limits

- **~52 publications per page.** Ghost Explore curates roughly 52 sites per ranking page. There is no server-side pagination on the category page. To cover more publications, crawl more categories.
- **Member counts are opt-in.** Publications choose whether to display their member count. When `show_members` is false, `member_count` is null.
- **The directory is curated, not exhaustive.** Ghost Explore lists a curated subset of Ghost publications, not every Ghost site in existence.
- **Revenue figures come from testimonials.** When a publication supplies a testimonial with revenue or subscriber figures, they appear in `testimonial`. This is self-reported.
- **Duplicate publications across categories.** The same publication appears on multiple pages (e.g. Top Members and Tech). Each occurrence is written with its own `category` and `rank`.

### FAQ

**Do I need an API key?**
No. The directory is public HTML and the RSS endpoint is public JSON.

**How many publications are in Ghost Explore?**
The directory lists a curated subset of Ghost publications across its category pages. Crawling all 35+ categories yields the widest coverage.

**What is the difference between `top` and `top-members`?**
`top` is Ghost's editorial top pick. `top-members` ranks by subscriber count. `top-revenue` ranks by revenue.

**Can I get the author's contact email?**
The staff roster carries social links but not email addresses. Ghost Explore does not publish emails.

**What does the `testimonial` field contain?**
The owner's quote, which frequently includes subscriber counts and revenue figures — for example "we have 75,000 paying subscribers, roughly $4M in gross yearly revenue".

**Why does the same site appear multiple times?**
Because it ranks on multiple category pages. Each row records its own `category` and `rank`. Filter by `category` for a deduplicated per-page view.

### Support

Open an issue on the Actor's page for bugs or feature requests.

### Changelog

#### 0.1 — 2026-10-03

- Initial build. Keyless extraction of the Ghost Explore newsletter directory.
- Parses the `data-*` payload embedded in each `a[data-site-slug]` anchor: name, description, external URL, icon, accent color, member count, staff roster, testimonial, ActivityPub handle.
- 35+ supported category and ranking pages plus a language filter.
- Optional RSS enrichment via the public `/api/sites/{slug}/rss` JSON endpoint.
- Rank and source page recorded per row so the same publication can be compared across rankings.
- Retries on 429 and 5xx with backoff.
- No login, no API key, no JavaScript rendering.

# Actor input Schema

## `categories` (type: `array`):

Slugs to crawl. Ranking pages: top, top-members, top-revenue, trending, recent, social-web, personal. Topic pages: tech, business, programming, news, finance, culture, travel, education, art, faith-spirituality, health, literature, sport, entertainment, productivity, design, food-drink, music, crypto, science, fiction, gaming, nature-outdoors, house-home, fashion-beauty, podcasts, gear-gadgets, history, parenting, climate, youtubers. Leave empty to crawl the four main ranking pages.

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

Two-letter language code (en, fr, es, de, it, pt, ja, pl, nl, ko) or empty for all languages.

## `includeRssPosts` (type: `boolean`):

Fetch each publication's recent posts from the public RSS API. Adds one request per publication.

## `maxRssPosts` (type: `integer`):

Cap the number of recent posts attached per publication.

## `maxResultsPerCategory` (type: `integer`):

Cap records written per category page.

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

Defaults to Apify datacenter proxy. Ghost Explore accepts datacenter IPs.

## Actor input object example

```json
{
  "categories": [
    "top-members",
    "top-revenue",
    "trending",
    "recent"
  ],
  "language": "",
  "includeRssPosts": false,
  "maxRssPosts": 5,
  "maxResultsPerCategory": 200,
  "proxy": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `dataset` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("aurenic/ghost-explore-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("aurenic/ghost-explore-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 '{}' |
apify call aurenic/ghost-explore-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,aurenic/ghost-explore-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/fqmJJPnvGm7NVO9UP/builds/VkRQVepJUC1zoUnZY/openapi.json
