# 9GAG Scraper — Trending Posts, Votes & Comments (`logiover/ninegag-post-scraper`) Actor

Scrape 9GAG, one of the largest meme and entertainment communities on the web. Extract post title, permalink, section, media type, upvotes and downvotes, net score, comment count, publish date, NSFW and promoted flags and image across every section.

- **URL**: https://apify.com/logiover/ninegag-post-scraper.md
- **Developed by:** [Logiover](https://apify.com/logiover) (community)
- **Categories:** Social media, News
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.10 / 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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## 9GAG Scraper — Trending Posts, Votes & Comments

One of the web's largest meme and entertainment communities in rows: post title, permalink, section, media type, upvotes and downvotes, net score, comment count, publish date and NSFW and promoted flags.

### What does the 9GAG Scraper do?

This Actor collects posts from **9GAG**, one of the largest meme and entertainment communities online. You pick a section and a listing — Hot or Fresh — and it returns the feed, one row per post, with the full voting and comment picture.

The feed is **cursor-paged**, not numbered: each response hands back the token needed to fetch the block after it, so pages cannot be requested out of order or in parallel. This Actor threads that cursor through the run, which is the only ordering the endpoint will serve, and stops cleanly when the feed hands back no further token.

Both vote directions are kept, and their difference is calculated into `score`. On a community that votes both ways, a post with 1,400 up and 70 down is a very different thing from one with 1,400 up and 700 down, and only the net figure shows it.

### Who is it for?

- **Social media analysts** tracking what spreads on a large meme community.
- **Brand and agency teams** watching internet culture for campaign material.
- **Trend researchers** measuring how quickly a topic surfaces and decays.
- **Content platforms** benchmarking engagement against a mature community.
- **Academics** studying voting behaviour and virality.
- **Meme and media aggregators** seeding a catalogue of trending content.

### Use cases

- Track what is trending in a section day by day.
- Rank posts by net score rather than upvotes to find genuinely well-received content.
- Compare comment count against votes to find the posts people argue about.
- Measure how the Hot and Fresh feeds diverge over a day.
- Filter out promoted posts to see the organic feed only.
- Build a dataset of titles for text and topic analysis.
- Feed an AI agent trending posts for internet-culture questions.

### Why use this 9GAG Scraper?

- **Both vote directions plus the net score**, not just upvotes.
- **Cursor paging handled properly**, so a long run keeps advancing instead of re-serving the first block.
- **Promoted and NSFW flags** kept, so you can separate paid from organic and filter adult content.
- **Publish dates converted to ISO** from unix timestamps.
- **Any section** — pass the name straight from a 9GAG URL.
- **Keyless, login-free and proxy-free.**

### What data can you extract?

One row per post. Anything the source left blank comes back as `null`.

| Field | Description |
| --- | --- |
| `postId` | 9GAG post ID |
| `url` | Link to the post |
| `title` | Post title |
| `section` | Section the post belongs to |
| `mediaType` | Photo, Animated or Video |
| `upVotes` | Upvote count |
| `downVotes` | Downvote count |
| `score` | Upvotes minus downvotes |
| `comments` | Comment count |
| `publishedAt` | Publish date as ISO |
| `isNsfw` | Yes or No |
| `isPromoted` | Yes or No |
| `imageUrl` | Post image |
| `scrapedAt` | ISO timestamp of collection |

#### Sample output

```json
{
  "postId": "azxNKxq",
  "url": "http://9gag.com/gag/azxNKxq",
  "title": "Actual journalism",
  "section": "iam_god",
  "mediaType": "Animated",
  "upVotes": 1397,
  "downVotes": 73,
  "score": 1324,
  "comments": 147,
  "publishedAt": "2026-08-22T04:40:18.000Z",
  "isNsfw": "No",
  "isPromoted": "No",
  "imageUrl": "https://img-9gag-fun.9cache.com/photo/azxNKxq_460s.jpg",
  "scrapedAt": "2026-08-22T09:38:15.311Z"
}
```

### How to use the 9GAG Scraper

#### Option A — the main feed

Leave **Section** as `default` and **Listing** on *Hot*, set **Maximum results** and run.

#### Option B — one section

Put a section name in **Section** — `funny`, `gaming`, `wholesome`, `memes` — copied from a 9GAG URL.

#### Option C — a trend series

Schedule a daily run on the same section and diff by `postId` to see what entered and left the feed.

### Input parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `section` | string | `default` | Section name as it appears in a 9GAG URL |
| `listing` | select | `hot` | `hot` ranks by engagement, `fresh` is newest first |
| `maxResults` | integer | 1000 | Stop after this many posts (max 20,000) |
| `proxyConfiguration` | object | *(off)* | Optional; the public feed answers without one |

### Tips for best results

- **Rank by `score`, not `upVotes`.** A heavily downvoted post can still show a big upvote number; the net figure is what the community actually settled on.
- **Filter `isPromoted` out** before measuring organic engagement — paid posts distort every average.
- **Use `comments` against `score`** to find controversy: high comments with a modest score usually means an argument.
- **Fresh moves faster than Hot.** For a trend series, schedule Fresh more frequently.
- **Deduplicate on `postId`** when combining scheduled runs; a post can stay in Hot for days.

### Integrations

Connect the dataset to Make, Zapier, Airbyte, Google Sheets, Slack, GitHub or any HTTP endpoint through Apify integrations, or schedule a run and push results into a warehouse with a webhook.

### API usage

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("logiover/ninegag-post-scraper").call(run_input={
    "section": "funny",
    "listing": "hot",
    "maxResults": 2000,
})
rows = list(client.dataset(run["defaultDatasetId"]).iterate_items())
organic = [r for r in rows if r["isPromoted"] == "No"]
top = sorted(organic, key=lambda r: r["score"] or 0, reverse=True)[:5]
for r in top:
    print(r["score"], r["title"])
```

### Use with AI agents (MCP)

The Actor is callable from the Apify MCP server, so an assistant can pull trending posts directly and answer questions about what is spreading online.

### FAQ

#### Do I need a 9GAG account or API key?

No. This Actor reads the public feed; there is nothing to register.

#### How many posts can one run return?

Up to 20,000, ten per request. The feed is cursor-paged, so requests run one after another rather than in parallel — expect a few hundred posts in well under a minute.

#### Why is paging slower than on other scrapers?

Because the endpoint will not serve a page you ask for by number. Each response contains the token for the next block, so the run has to walk the feed in order. Requesting blocks in parallel simply returns the same one repeatedly.

#### What sections are available?

Any name that appears in a 9GAG URL — `default` for the main feed, plus `funny`, `gaming`, `wholesome`, `memes`, `wtf` and the rest.

#### What is the difference between Hot and Fresh?

Hot is ranked by engagement and moves slowly; Fresh is newest-first and turns over quickly. Use Fresh if you want to catch posts early.

#### Does it collect comments themselves?

No, only the comment count. This Actor covers the feed record; individual comment threads are a separate request per post.

#### Can I filter out adult content?

Yes — every row carries `isNsfw`, so filter on it after the run.

#### Can I export to CSV or Excel?

Yes — every run's dataset exports to JSON, CSV, Excel, XML or JSONL.

#### How fresh is the data?

Each run reads the feed live, so vote and comment counts are as current as 9GAG's own at the moment you run it.

#### Why did my run return fewer posts than requested?

Because the feed ran out of cursor. The Actor logs that plainly and stops rather than looping on the last block.

### Is it legal to scrape 9GAG?

This Actor reads 9GAG's public feed — no accounts, no logins, no private content. Post titles, vote counts and permalinks are information published for public view. Uploader identities are not collected. You remain responsible for how you use the results, including any copyright in the images themselves, which belong to their creators, and for respecting the platform's terms in your own jurisdiction.

### Related scrapers

- **Bilibili Scraper** — trending videos and engagement from China's video community.
- **Reddit Historical Archive Scraper** — full-subreddit post archives.
- **Threads Scraper** — posts and engagement.
- **Bluesky Historical Archive Scraper** — full-feed social archives.

***

\*Maintained: last verified 2026-09-01 — checked end-to-end against live run history (reliability, output fields and types, and time/memory budgets).

# Actor input Schema

## `section` (type: `string`):

Section name as it appears in a 9GAG URL, e.g. default for the main feed, funny, gaming, wholesome, memes.

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

Hot ranks by engagement; Fresh is newest first.

## `maxResults` (type: `integer`):

Stop after this many posts. Each request returns 10.

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

9GAG's public feed answers without a proxy. Enable one if you hit rate limiting on large runs.

## Actor input object example

```json
{
  "section": "default",
  "listing": "hot",
  "maxResults": 1000,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Every record collected in this run. Open the Dataset tab to browse, filter or export as JSON, CSV or Excel.

# 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 = {
    "section": "default",
    "listing": "hot",
    "maxResults": 1000,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("logiover/ninegag-post-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 = {
    "section": "default",
    "listing": "hot",
    "maxResults": 1000,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("logiover/ninegag-post-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 '{
  "section": "default",
  "listing": "hot",
  "maxResults": 1000,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call logiover/ninegag-post-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,logiover/ninegag-post-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/T1OQ3fuQer8lYcZcE/builds/pK7ZeNCu8HuWU7DUj/openapi.json
