1. 2scraper
  2. Publishing & community
  3. Perplexity
Open source · MITNeeds a residential exit or the Scraping Browser API

Perplexity Scraper

Perplexity Pages and Discover articles — authors, counters and every cited source — from the site's own article API.

  • Playwright
  • Selenium
  • Puppeteer
  • Scraping Browser API
  • Scraper API
  • JSON
  • CSV
perplexity-scraper
# Discover feed
$ python3 playwright_scraper.py --discover top --max-results 40 --format csv --out discover.csv
✓ 2 sample rows · 24 columns in sample_output.json
2article kinds: Pages and Discover
25/25articles on a Discover run, live (Sep 2026)
20Discover articles per feed page
4ways to run: 3 browser engines + Scraper API
Available Perplexity scrapers

What the Perplexity scraper collects

Reads public perplexity.ai articles — classic Pages (/page/...) and Discover articles — from a URL, a file of URLs or the Discover feed. Each row comes from the site's own /rest/article/ API: title, author, summary, publish and update times, view, like and fork counts, every cited source, and section and word counts, as JSON or CSV.

Discover feed

Input: A Discover topic (top)

Reads the feed 20 articles per page up to --max-results, then fetches each article's full record.

Single article

Input: A classic Page or Discover article URL

One row with title, author, counters, summary, timestamps and every cited source.

URL batch

Input: A text file, one article URL per line

One row per article; dead URLs are reported as not found, never as blocks.

No local browser

Input: TWOCAPTCHA_KEY and a profile in .env

The feed and every article API call go through 2Captcha's Scraper API, routed through your Scraping Browser profile.

Quick start

From zero to Perplexity data in 3 steps

  1. Install

    Clone the repository and install one browser engine. Python 3.9+.

    $ git clone https://github.com/2scraper/perplexity-scraper.git && cd perplexity-scraper
    $ python3 -m venv .venv && source .venv/bin/activate
    $ pip install -r requirements-playwright.txt
    $ playwright install chromium
    $ cp .env.example .env
    $ python3 playwright_scraper.py --discover top --max-results 20
  2. Run a scraper

    Pick what you need and run it. Every flag is documented in the README.

    $ python3 playwright_scraper.py --discover top --max-results 40 --format csv --out discover.csv
  3. Get structured data

    Rows land in JSON or CSV (--format), with a .meta.json sidecar recording status, pages fetched and why the run stopped.

Output

Perplexity data fields

24 columns per row in a predictable schema. The most useful ones:

FieldWhat it holds
skuperplexity- plus the article's stable 22-character id
titleArticle title
authorThe article's author handle
categoryThe Discover topic; null for a classic Page
product_urlThe article's canonical URL
summaryDiscover summary; null for a classic Page
view_countThe site's view counter
like_countThe site's like counter
fork_countThe site's fork counter
sources_jsonEvery distinct cited source as JSON {url, title}
source_countNumber of distinct cited sources
section_countNumber of sections in the article
word_countWords across the whole article
read_time_minutesRead time as the site reports it
published_atPublish time
updated_atLast update time
[
  {
    "sku": "perplexity-VzUTuvQVSIqru3QGvPihlg",
    "source": "perplexity.ai",
    "category": null,
    "title": "Perplexity AI Pages Guide: Generate & Share Content Seamlessly",
    "brand": null,
    "price": null,
    "currency": null,
    "price_source": null,
    "product_url": "https://www.perplexity.ai/page/perplexity-ai-pages-guide-gene-VzUTuvQVSIqru3QGvPihlg",
    "image_url": "https://pplx-res.cloudinary.com/image/fetch/s--mc_0liAQ--/t_limit/https://framerusercon…",
    "scraped_at": "2026-09-30T08:34:56Z",
    "author": "perplexity_guy",
    "view_count": 2280,
    "like_count": 0,
    "fork_count": 30,
    "source_count": 38,
    "sources_json": "[{\"url\": \"https://www.youtube.com/watch?v=EH3886nGmOk\", \"title\": \"Perplexity Pages - Th…",
    "section_count": 14,
    "word_count": 1758,
    "slug": "perplexity-ai-pages-guide-gene-VzUTuvQVSIqru3QGvPihlg",
    "summary": null,
    "read_time_minutes": 8,
    "published_at": "2024-06-01T22:51:39.145100+00:00",
    "updated_at": "2024-07-08T16:35:32.009233"
  },
  {
    "sku": "perplexity-heYaECNnQuaM0AZ0QSWjaw",
    "source": "perplexity.ai",
    "category": "top",
    "title": "OpenAI unveils Dots, an always-on AI agent, at DevDay 2026",
    "brand": null,
    "price": null,
    "currency": null,
    "price_source": null,
    "product_url": "https://www.perplexity.ai/discover/top/openai-unveils-dots-an-always-heYaECNnQuaM0AZ0QS…",
    "image_url": "https://pplx-res.cloudinary.com/image/fetch/s--ujP6_Ewb--/t_limit/https://static.simonw…",
    "scraped_at": "2026-09-30T08:35:03Z",
    "author": "pagesandbits",
    "view_count": 0,
    "like_count": 0,
    "fork_count": 0,
    "source_count": 6,
    "sources_json": "[{\"url\": \"https://openai.com/index/introducing-dots/\", \"title\": \"Introducing dots\"}, {\"…",
    "section_count": 4,
    "word_count": 380,
    "slug": "openai-unveils-dots-an-always-heYaECNnQuaM0AZ0QSWjaw",
    "summary": "Powered by GPT-6 Astra, each Dot gets its own cloud computer and can connect to over 4,…",
    "read_time_minutes": 3,
    "published_at": "2026-09-29T17:14:10.246772+00:00",
    "updated_at": "2026-09-29T17:15:35.292639"
  }
]

First 2 of 2 rows from a real run — sample_output.json. Long values shortened here.

Built for Perplexity

Handles what breaks naive Perplexity scrapers

The article API, not the markup

The HTML's meta tags are the same on every page, so rows come from /rest/article/{id}, called with fetch() from inside the article page where the browser already holds the site's cookies.

Throttling handled, not hidden

A refused API call is retried after 3, 5, 8 and 15 seconds, and articles are paced 2 s apart — at 0.5 s the API throttled after 13. A run that still gets throttled says rate_limited, never complete.

Not found is not blocked

An API 400 means the article does not exist: no row, no retry, and not counted as a block. Only a challenge that never cleared or a persistent refusal is reported as blocked.

Every cited source, deduplicated

Sources are collected across all sections, deduplicated, and stored as a flat JSON string so a CSV row stays one row.

Everything built in

Scraping infrastructure included

The same tested core runs every 2scraper repository, so the hard parts work the same way on every site.

CAPTCHA handling

Detects the challenge a page really serves and, with a 2Captcha key, solves it only when it blocks the data — a capped number of solves per page.

Proxy rotation

Single proxy or a pool from a file, rotated on blocks with a fresh browser per exit. Credentials stay out of argv and logs.

Fingerprints

Optional complete device identity from the 2Captcha Fingerprint API — user agent, client hints, locale and timezone that agree with each other.

Scraping Browser API

Point --cdp-endpoint at a managed Chromium with its own exit country — no browser infrastructure to run yourself.

Honest run metadata

Every run writes a .meta.json sidecar and distinct exit codes: complete, blocked, empty and partial are never confused, and a failed run never overwrites good data.

Diff two runs

diff_runs.py compares two complete Perplexity snapshots by id — new, removed and changed rows for monitoring.

Use cases

What teams do with Perplexity data

Citation analysis

See which domains Perplexity's articles cite and how often, from sources_json across many articles.

Content and trend monitoring

Snapshot the top Discover feed daily and diff runs to see which stories enter and leave it.

Engagement tracking

Follow view, like and fork counters on specific Pages over time.

Research corpora

Collect article titles, summaries, word counts and sources for media or AI-search research.

Access & pricing

Free to run. Pay only for what the site requires.

Needs a residential exit or the Scraping Browser API

Cloudflare kept every local browser tried on its challenge page, so the recommended setup is a 2Captcha Scraping Browser API profile (US) in .env — it got through on every live run of 2026-09-30 and 2026-10-01 with no paid captcha solves. Alternatively the 2Captcha Scraper API runs it with no browser at all, routed through the same profile. This repo does not implement a local captcha solver, so a local run without the Browser API is reported as blocked.

Optional 2Captcha services — captcha solving, the Scraping Browser API, residential proxies and fingerprints — work behind one key.

Good to know

  • Local browsers were blocked by Cloudflare in every test; use the Scraping Browser API or the Scraper API.
  • One Scraping Browser connection per profile; a second run started right away can time out.
  • Only the top Discover topic has items for an anonymous visitor.

2scraper vs. hosted scraper APIs

2scraperTypical hosted API
CodeOpen source, MIT — read and patch itClosed
CostFree; optional services billed only when usedSubscription or per request / per result
Runs onYour machine, server or CIThe vendor's infrastructure
OutputJSON/CSV files + run metadataAPI responses
When the site changesFix it yourself or open an issue / PRWait for the vendor
FAQ

Perplexity scraper FAQ

Which Perplexity content can it read?

Published articles: classic Pages (/page/...) and Discover articles (/discover/{topic}/...). Live answers, accounts and anything behind a login are out of scope.

Do I need a paid product?

In practice yes: local browsers were held on Cloudflare's challenge in every test, while a Scraping Browser API profile got through. Put it in PERPLEXITY_CDP_ENDPOINT in .env.

Which Discover topics work?

Only top has items for an anonymous visitor; other topics return an empty feed (exit 4).

Why do some counters read 0?

The site's view, like and fork counters can read 0 for about a day after an article is published.

What output does it produce?

JSON or CSV, one row per article, plus a .meta.json sidecar with status, failed URLs and whether --max-results capped the run. A run that collects nothing never overwrites your last good file.

Is it legal to scrape Perplexity?

It reads public articles only and skips paths robots.txt disallows. Public data; follow the site's terms and the law.