     [Blog](https://scrapfly.io/blog)   /  [ai](https://scrapfly.io/blog/tag/ai)   /  [How to Scrape Perplexity AI in 2026](https://scrapfly.io/blog/posts/how-to-scrape-perplexity)   # How to Scrape Perplexity AI in 2026

 by [Hisham Medhat](https://scrapfly.io/blog/author/hisham) Jul 07, 2026 19 min read [\#ai](https://scrapfly.io/blog/tag/ai) [\#hidden-api](https://scrapfly.io/blog/tag/hidden-api) [\#python](https://scrapfly.io/blog/tag/python) [\#scrapeguide](https://scrapfly.io/blog/tag/scrapeguide) 

 [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-perplexity "Share on LinkedIn")    

 

 

         

   **Web Scraping API**Scrape any website with anti-bot bypass, proxy rotation, and JS rendering.

 

 [ Learn More  ](https://scrapfly.io/products/web-scraping-api) [  Docs ](https://scrapfly.io/docs/scrape-api/getting-started) 

 

 

Perplexity AI reads about ten pages per query and cites three or four. If your domain isn't in that handful, you're invisible in AI search for that query. The only direct way to find out is to scrape Perplexity's answers and read the citations.

This guide builds that scraper in Python with Scrapfly, then turns it into a citation tracker for your citation rate over time. If you actually came for "use the Perplexity API to parse HTML," the next section gives the honest answer.



## Key Takeaways

- **Scrape Perplexity to measure AI-search visibility.** See if your domain gets cited.
- **One Scrapfly call returns structured JSON.** It renders the SPA and clears Cloudflare.
- **`cited_domains` is the field that matters.** It names every source Perplexity cited.
- **Wait for the `Helpful` button or you capture half an answer.** A `js_scenario` handles it.
- **Came to use Perplexity as a parser?** `extraction_prompt` does that in one call.
- **[Scrapfly](https://scrapfly.io/products/web-scraping-api) does the fetching.** You focus on the citation data.

**Get web scraping tips in your inbox**Trusted by 100K+ developers and 30K+ enterprises. Unsubscribe anytime.







[**Perplexity Scraper**github.com/scrapfly/scrapfly-scrapers/tree/main/perplexity-scraper](https://github.com/scrapfly/scrapfly-scrapers/tree/main/perplexity-scraper)

## Are You Trying to Scrape Perplexity AI, or Use Perplexity to Scrape?

This article shows how to scrape perplexity.ai for AI-generated answers and citations. If you came looking for "use the Perplexity API as a parsing layer inside your own scraper," Scrapfly handles that natively. One call replaces the multi-service stack.

The motivation is real. HTML is volatile, CSS selectors break, and an LLM that "reads" a page survives layout changes you'd otherwise maintain across ten sites. The need is sound; the multi-service pattern is heavier than needed.

Scrapfly's [Web Scraping API](https://scrapfly.io/web-scraping-api) includes `extraction_prompt`, a natural-language LLM parameter that runs inline with the scrape. One call fetches the page, renders JS, bypasses anti-bot, and returns parsed JSON. No extra key, no glue code.

Here's the full pattern in ten lines:

python```python
from scrapfly import ScrapflyClient, ScrapeConfig

client = ScrapflyClient(key="YOUR_SCRAPFLY_API_KEY")

result = client.scrape(ScrapeConfig(
    url="https://web-scraping.dev/product/1",
    render_js=True,
    asp=True,
    extraction_prompt="Extract the product as JSON with fields: name, price, description, brand, rating.",
))

print(result.scrape_result["extracted_data"]["data"])
# {'brand': 'ChocoDelight', 'rating': '4.7', 'name': 'Box of Chocolate Candy', 'price': '$9.99', ...}
```



That single call replaces a Perplexity API call, a stealth browser, a proxy rotator, and the glue between them. See the [Extraction API LLM prompt docs](https://scrapfly.io/docs/extraction-api/llm-prompt) and the [Web Scraping API extraction integration](https://scrapfly.io/docs/scrape-api/extraction) for the full surface.

One narrow concession: if your team is already standardized on the Perplexity API, run Scrapfly for the fetch and pass the cleaned HTML to your existing Perplexity call. Perplexity then slots in as the LLM in your stack, not as a scraping product.

For everyone scraping Perplexity itself, the rest of this guide is a working Python tutorial.



## Why Scrape Perplexity AI?

Developers and SEO teams scrape Perplexity for three reasons: tracking brand citations, mapping authoritative sources for buyer-intent queries, and ground-truthing API output against the live UI.

Perplexity visits roughly ten pages per query and cites three or four in the final answer.

For B2B SaaS teams, a citation rate of 20-30% across tracked buyer-intent prompts is the working target. Below 10% means you're invisible in AI search for that category; above 40% means you're a category leader.

Two reader profiles show up. The first is a developer building an AEO dashboard who needs programmatic answers and source lists, not a screenshot dump. The second is an SEO lead who needs hard data on category visibility, not GA4 referral noise.

GA4 referral data is too slow and lossy for direct measurement. Perplexity surfaces sources without always sending clicks, and attribution drops many of those visits. Scraping the live UI is the only sure way to know your citation rate.

The API-versus-UI consistency check is its own use case. Teams already running the Perplexity API for production tasks scrape the UI periodically to confirm the API answers match what real users see.

[How to Bypass Cloudflare When Web Scraping in 2026Cloudflare offers one of the most popular anti scraping service, so in this article we'll take a look how it works and how to bypass it.](https://scrapfly.io/blog/posts/how-to-bypass-cloudflare-anti-scraping)



## What Data Can You Scrape from Perplexity?

A single Scrapfly call returns six fields: prompt, AI answer text, cited source domains, source count, follow-up questions, and the final thread URL. Together they cover what an AEO tracker or AI-visibility audit needs.

Here are the fields:

- `query`: the prompt you submitted
- `thread_url`: final public Perplexity thread URL after redirect (`/search/{uuid}`)
- `answer_markdown`: full AI-generated response in markdown / readable text
- `cited_domains`: unique source domain strings cited under the answer, parsed from inline source labels and favicon image URLs
- `source_count`: integer from the visible "N sources" label
- `follow_ups`: Perplexity's suggested follow-up questions
- `scraped_at`: ISO timestamp

The screenshot below shows a typical Perplexity result page. The answer area has inline source chips (`wikipedia +1`, `geeksforgeeks +1`), the `Answer / Links / Images` tabs up top, and the `10 sources` button with the `Follow-ups` heading at the bottom.



Clicking the `Links` tab swaps the answer for the full source list, with each row showing position, title, URL, and domain:



A real result from the scraper looks like this:



Outputjson```json
{
  "query": "What are the proven health benefits of green tea?",
  "thread_url": "https://www.perplexity.ai/search/13a2415a-3a7d-4d71-88c7-f73219de3839",
  "answer_markdown": "Green tea has several well-supported health benefits, largely tied to its antioxidant polyphenols (especially catechins like EGCG). Evidence in humans is strongest for metabolic and heart markers and cardiovascular risk, while effects on cancer and other outcomes are more mixed. ...",
  "cited_domains": ["pmc.ncbi.nlm.nih.gov", "health.clevelandclinic.org", "healthline.com"],
  "source_count": 10,
  "follow_ups": [
    "How much green tea should you drink daily for benefits",
    "Green tea and cardiovascular risk reduction evidence",
    "Differences between green tea types (Sencha, Matcha) in health impact"
  ],
  "scraped_at": "2026-07-01T08:22:00Z"
}
```







The `cited_domains` field is the one that matters for AEO measurement. Every entry is a bare domain you can compare directly against `your-domain.com` to count whether you appear in the citation list.

If you need full source rows with title and URL, add a `js_scenario` that clicks the `Links` tab before extraction. The tab swaps the Answer view for the source list, so `follow_ups` drops out of the scrape.

Pick whichever fits. The default scrape returns the domain list plus follow-ups, while the Links-tab variant returns full URLs with titles. The next section shows the `js_scenario` block.



Scrapfly

#### Scale your web scraping effortlessly

Scrapfly handles proxies, browsers, and anti-bot bypass — so you can focus on data.

[Try Free →](https://scrapfly.io/register)## Project Setup

Install `scrapfly-sdk` and get a Scrapfly API key from your [Scrapfly dashboard](https://scrapfly.io/dashboard). That's the entire setup.

bash```bash
pip install scrapfly-sdk
```



Then create a client instance once and reuse it across calls:

python```python
from urllib.parse import quote_plus
from scrapfly import ScrapeConfig, ScrapflyClient

client = ScrapflyClient(key="YOUR_SCRAPFLY_API_KEY")
```



The rest of this article uses only `scrapfly-sdk` and the Python standard library. No `playwright-stealth`, no `BeautifulSoup`, no `pydantic`. New to Python scraping? Start with [web scraping with Python](https://scrapfly.io/blog/posts/web-scraping-with-python) for the basics.

## How to Submit a Perplexity Query

Perplexity accepts a public search URL at `https://www.perplexity.ai/search?q={prompt}`. It redirects through `/search/new?q={prompt}` and auto-creates a public thread at `/search/{uuid}` once JavaScript runs.

URL-driven navigation is the primary entry point; you don't need to simulate a form submit.

A live check confirms the chain: `/search?q=test` returns a 301 to `/search/new?q=test`, and the JS browser creates the final thread at `/search/{uuid}`. Scrapfly returns that final URL after the scrape, useful for debugging.

The default scrape adds a short `js_scenario` that waits for the answer to finish rendering before extraction; the next sections show it. Dismissing the cookie banner or clicking the `Links` tab are optional actions on top of that.

python```python
from urllib.parse import quote_plus

prompt = "What are the proven health benefits of green tea?"
url = f"https://www.perplexity.ai/search?q={quote_plus(prompt)}"

# The default scrape passes a js_scenario that waits for the answer to finish
# (shown below). Dismissing the cookie banner is optional, only if it covers
# the answer during validation.
js_scenario = [
    {"click": {"selector": '//button[contains(., "Necessary Cookies")]',
               "ignore_if_not_visible": True}},
    {"wait": 1000},
]
```



The public search URL is stable. Perplexity's internal API endpoints (`/rest/sse/perplexity_ask`, `/rest/thread/...`) change without notice and require auth for most reads, so the public URL route stays the right entry point.

[How to Scrape Hidden APIsIn this tutorial we'll be taking a look at scraping hidden APIs which are becoming more and more common in modern dynamic websites - what's the best way to scrape them?](https://scrapfly.io/blog/posts/how-to-scrape-hidden-apis)

## How to Scrape Perplexity Search Results

One Scrapfly Web Scraping API call covers the whole flow. It sends the URL-driven query, renders JS, bypasses Cloudflare with `asp=true`, waits for the answer to finish with a `js_scenario`, and extracts JSON with `extraction_prompt`.

python```python
from urllib.parse import quote_plus
from datetime import datetime
from scrapfly import ScrapeConfig, ScrapflyClient

client = ScrapflyClient(key="YOUR_SCRAPFLY_API_KEY")

EXTRACTION_PROMPT = (
    "Extract a JSON object from this Perplexity result page with the fields below. "
    "Ignore the left sidebar navigation, history list, cookie banner, sign-in modal, "
    "and the follow-up composer at the bottom.\n"
    "Fields:\n"
    "- query: original question above the answer\n"
    "- answer_markdown: the AI answer text only, with paragraph breaks\n"
    "- cited_domains: array of unique source domains cited under the answer. "
    "Include domains from inline source labels, inline anchor URLs, and from "
    "\"domain=...\" parameters in favicon image URLs near the source list. "
    "Return the FULL registrable domain including its TLD, for example "
    "\"healthline.com\" or \"pmc.ncbi.nlm.nih.gov\". Never drop or truncate the TLD, "
    "and include no protocol and no path.\n"
    "- source_count: integer from the \"N sources\" label\n"
    "- follow_ups: array of strings under the Follow-ups heading\n"
    "Return only the JSON object."
)

# Wait for the answer to finish streaming, then let trailing edits settle.
JS_SCENARIO = [
    {"wait_for_selector": {"selector": "button[aria-label='Helpful']",
                           "state": "visible", "timeout": 10000}},
    {"wait": 10000},
]

def scrape_perplexity(prompt: str) -> dict:
    url = f"https://www.perplexity.ai/search?q={quote_plus(prompt)}"
    result = client.scrape(ScrapeConfig(
        url=url,
        render_js=True,
        asp=True,
        country="us",
        proxy_pool="public_residential_pool",
        rendering_wait=15000,
        js_scenario=JS_SCENARIO,
        extraction_prompt=EXTRACTION_PROMPT,
    ))
    data = result.scrape_result.get("extracted_data", {}).get("data", {}) or {}
    return {
        "query": prompt,
        "thread_url": result.scrape_result.get("url"),
        "answer_markdown": data.get("answer_markdown"),
        "cited_domains": data.get("cited_domains") or [],
        "source_count": data.get("source_count"),
        "follow_ups": data.get("follow_ups") or [],
        "scraped_at": datetime.utcnow().isoformat() + "Z",
    }
```



`scrape_perplexity("What are the proven health benefits of green tea?")` returns the canonical JSON shape from the previous section in a few seconds. The next four subsections explain each parameter.

### Configuring the Scrapfly Request

`render_js=True` runs a real Chromium so Perplexity's React SPA can hydrate and produce the answer. `asp=True` enables Anti Scraping Protection, which handles Cloudflare challenges, fingerprinting, and IP reputation in one parameter.

`country="us"` pins the exit IP because Perplexity localizes answers by IP. `proxy_pool="public_residential_pool"` routes through residential IPs because Perplexity throttles datacenter ASNs.

python```python
ScrapeConfig(
    url=url,
    render_js=True,   # required, Perplexity is a React SPA
    asp=True,         # bypasses Cloudflare on perplexity.ai
    country="us",     # consistent locale, US sources
        proxy_pool="public_residential_pool",  # residential IPs; datacenter ASNs get throttled
)
```



Without `render_js=True`, the page returns an empty React shell. Without `asp=True`, Cloudflare blocks the request before any HTML loads.

### Opening the Query URL and Optional UI Actions

Build the query URL with `quote_plus(prompt)` and let the browser follow redirects to the final `/search/{uuid}` thread page. Scrapfly returns the final URL in `result.scrape_result["url"]` so you can capture and store it.

To capture full source rows (title + URL + domain), add a `js_scenario` that clicks the `Links` tab before extraction. The trade-off is that when the Links tab is active, the Follow-ups heading isn't on the page, so `follow_ups` returns empty.

python```python
js_scenario = [
    {"click": {"selector": '//*[normalize-space(text())="Links"][not(self::script)]',
               "ignore_if_not_visible": True}},
    {"wait": 2500},
]
# Pass js_scenario=js_scenario into ScrapeConfig when you need full source rows.
# Skip it when you'd rather have follow_ups + cited_domains in one shot.
```



Direct calls to Perplexity's internal endpoints (`/rest/sse/perplexity_ask`, `/rest/thread/...`) stay out of scope because they shift without notice and require auth for most reads. The public URL route is the stable entry point.

### Detecting When the Streaming Response Completes

Perplexity streams the answer one token chunk at a time. A naive wait on `.markdown` returns the first chunk, not the full answer. The fix is a `js_scenario` that waits for a post-answer control, then pauses for trailing edits.

The feedback button works well. Perplexity shows a `Helpful` button only after streaming finishes, so `button[aria-label='Helpful']` is a stable completion signal. The trailing `wait` absorbs late edits after the first render.

python```python
JS_SCENARIO = [
    {"wait_for_selector": {"selector": "button[aria-label='Helpful']",
                           "state": "visible", "timeout": 10000}},
    {"wait": 10000},
]
```



Pair the scenario with `rendering_wait=15000` so the SPA has time to hydrate and start streaming before the scenario runs.

### Extracting Answers and Citations with `extraction_prompt`

`extraction_prompt` accepts natural language and returns structured JSON in `result.scrape_result["extracted_data"]["data"]`. The schema you describe is what the LLM enforces, so be specific about field names and what to ignore.

python```python
data = result.scrape_result["extracted_data"]["data"]
print(data["cited_domains"])
# ['pmc.ncbi.nlm.nih.gov', 'health.clevelandclinic.org', 'healthline.com']
```



The extraction prompt asks for `cited_domains` as bare domain strings. Full URLs and snippets live behind the source drawer. The domain tags in the answer text and favicon `domain=` parameters cover the citation question for AEO use cases.

## Bypass Perplexity Blocking with Scrapfly



ScrapFly's [Web Scraping API](https://scrapfly.io/products/web-scraping-api) is a single HTTP endpoint for collecting web data at scale, with a **99.99% success rate** across **130M+ proxies in 190+ countries**.

- [Anti-Scraping Protection bypass](https://scrapfly.io/docs/scrape-api/anti-scraping-protection) - automatically defeats Cloudflare, DataDome, PerimeterX, Akamai, and 90+ other bot systems.
- [Smart proxy rotation](https://scrapfly.io/docs/scrape-api/proxy) - residential and datacenter pools with country and ASN level geo-targeting.
- [JavaScript rendering](https://scrapfly.io/docs/scrape-api/javascript-rendering) - render SPAs and JS-driven pages through real cloud browsers.
- [Browser automation scenarios](https://scrapfly.io/docs/scrape-api/javascript-scenario) - scroll, click, fill forms, and wait for elements without managing a browser fleet.
- [Format conversion](https://scrapfly.io/docs/scrape-api/getting-started#api_param_format) - return pages as HTML, JSON, clean text, or LLM ready Markdown.
- [Session management](https://scrapfly.io/docs/scrape-api/session) - keep cookies, headers, and IPs consistent across multi step flows.
- [Smart caching](https://scrapfly.io/docs/scrape-api/getting-started#api_param_cache) - cache successful responses to cut cost on repeat scraping jobs.
- [Python](https://scrapfly.io/docs/sdk/python), [TypeScript](https://scrapfly.io/docs/sdk/typescript), [Scrapy](https://scrapfly.io/docs/sdk/scrapy), and [no-code integrations](https://scrapfly.io/docs/integration/getting-started) including [Make](https://scrapfly.io/integration/make), [n8n](https://scrapfly.io/integration/n8n), [Zapier](https://scrapfly.io/integration/zapier), [LangChain](https://scrapfly.io/integration/langchain), and [LlamaIndex](https://scrapfly.io/integration/llamaindex).

Perplexity sits behind Cloudflare, plus React-SPA fingerprinting and IP reputation checks. `asp=true` handles all three, with residential IPs and realistic fingerprinting on by default. Without it, a direct request hits a Cloudflare managed challenge.

The four DIY blockers and how Scrapfly handles each:

**Cloudflare on a React SPA.** A live direct HTTP check to perplexity.ai (May 2026) returned a Cloudflare managed challenge before any HTML loaded. `asp=true` solves this without hand-maintained challenge handling. The full response, JS render, and challenge solve happen in one Scrapfly request.

**Browser fingerprinting.** Perplexity also runs client-side fingerprinting on top of Cloudflare. Scrapfly's headless browser ships with realistic, drift-resistant fingerprints, so you don't maintain a stealth plugin stack across version bumps. The same configuration works whether you're scraping Perplexity, Cloudflare-protected e-commerce, or other SPA targets.

**Residential IP requirements.** Perplexity throttles datacenter ASNs heavily. Scrapfly routes through residential IPs with `proxy_pool="public_residential_pool"`, and the `country="us"` parameter pins the geography for consistent locale-dependent answers.

**Streaming-response completion logic.** The `js_scenario` that waits for the `Helpful` feedback button, covered in the previous section, is the clean, stable signal that streaming has finished. Polling for token-stream stability is unreliable because Perplexity sometimes streams trailing edits after the first complete render.

UI chrome adds one more parsing blocker. Cookie banners, sign-in modals, and the follow-up composer can pollute the page text. The extraction prompt above tells the LLM to ignore them; click "Necessary Cookies" during validation if a banner stays visible.

python```python
ScrapeConfig(
    url=url,
    render_js=True,
    asp=True,         # the one parameter that handles Cloudflare + fingerprint + IP
    country="us",
    proxy_pool="public_residential_pool",
    rendering_wait=15000,
    js_scenario=JS_SCENARIO,
    extraction_prompt=EXTRACTION_PROMPT,
)
```



Each blocker is solvable in isolation. The real cost is solving all of them on a target whose UI changes every few weeks, and `asp=true` collapses that into one parameter. See our [broader anti-bot bypass guide](https://scrapfly.io/blog/posts/how-to-bypass-anti-bot-protection-when-web-scraping) for other protected sites.

### Power your scraping with Scrapfly

Forget about getting blocked. Scrapfly handles anti-bot bypasses, browser rendering, and proxy rotation so you can focus on the data.



[Try for FREE!](https://scrapfly.io/register)





## How Do You Build a Perplexity Citation Tracker?

A Perplexity citation tracker runs a fixed prompt list, logs whether your domain appears in each answer's citations, and rolls up a citation rate over time. It's the AEO measurement layer on top of the scraping recipe.

A prompt list (text file or DB) feeds a loop that calls `scrape_perplexity()` for each prompt, checks `cited_domains` for your domain, and logs each run to SQLite. Roll up the matched runs to get a citation rate per week.

For B2B SaaS, target a 20-30% citation rate across your tracked prompts. Below 10% means you're invisible in AI search for those queries; above 40% means you're category-leading. A two-month run usually surfaces which prompts need content investment.

python```python
import json
import sqlite3
from datetime import datetime

# scrape_perplexity is the function defined above

def init_db(path="citations.db"):
    conn = sqlite3.connect(path)
    conn.execute("""
        CREATE TABLE IF NOT EXISTS runs (
            scraped_at TEXT,
            prompt TEXT,
            thread_url TEXT,
            source_count INTEGER,
            cited_domains TEXT,
            domain_matched INTEGER
        )
    """)
    return conn

def track_citations(prompts_file, your_domain, db_path="citations.db"):
    conn = init_db(db_path)
    matches = 0
    total = 0
    with open(prompts_file, encoding="utf-8") as fh:
        prompts = [line.strip() for line in fh if line.strip()]

    for prompt in prompts:
        result = scrape_perplexity(prompt)
        matched = int(any(
            your_domain in (d or "").lower()
            for d in result["cited_domains"]
        ))
        conn.execute(
            "INSERT INTO runs VALUES (?, ?, ?, ?, ?, ?)",
            (
                result["scraped_at"],
                prompt,
                result["thread_url"],
                result["source_count"],
                json.dumps(result["cited_domains"]),
                matched,
            ),
        )
        matches += matched
        total += 1
        print(f"{prompt[:60]:60s} matched={matched} domains={result['cited_domains']}")

    conn.commit()
    rate = matches / total if total else 0
    print(f"\nCitation rate for {your_domain}: {matches}/{total} = {rate:.1%}")
    return rate

# Usage:
# Create prompts.txt with one buyer-intent question per line, then:
# track_citations("prompts.txt", "your-domain.com")
```



A real run tracking `healthline.com` across a set of prompts looks like this. Swap in your own domain and your buyer-intent prompts:

text```text
What are the proven health benefits of green tea?            matched=1 domains=['pmc.ncbi.nlm.nih.gov', 'health.clevelandclinic.org', 'healthline.com']
What are the symptoms of vitamin D deficiency?               matched=0 domains=['unl.edu', 'webmd.com', 'healthdirect.gov.au', 'yalemedicine.org', 'clevelandclinic.org']
What foods are highest in magnesium?                         matched=0 domains=[]

Citation rate for healthline.com: 1/3 = 33.3%
```



You can also feed the cited domains back into a second Scrapfly call and scrape the competitor pages. That deeper analysis is its own article.



## FAQ

What is PerplexityBot, and is it the same as scraping Perplexity?PerplexityBot is the user agent Perplexity uses to crawl sites for its index. Scraping Perplexity is the opposite, sending prompts to perplexity.ai and harvesting answers and citations. PerplexityBot hits your logs; this guide sends requests, not receives them.







Does the Perplexity API return the same answers as the web UI?Often, but not always. The API and the web UI can route to different models and grounding for the same prompt. If you need ground-truth, user-visible output, scrape the UI; for volume and consistency, use the API.







How does Perplexity choose its sources and citations?Perplexity uses retrieval-augmented generation, fetching about ten pages per query and citing three or four. Choice depends on relevance, recency, and source authority, so scraping the citations and domain list shows how it ranks sources.







Can I scrape Perplexity Pro features (Spaces, attached files, Pro models)?Pro features sit behind login and need persistent session handling, so they stay out of scope here. The public search flow in this article needs no login and stops at the public answer plus cited domains.









## Summary

Scraping Perplexity programmatically is one Scrapfly call away. Render JS, clear Cloudflare with `asp=true`, open the query URL, wait for the answer to finish, then extract with `extraction_prompt`.

The citation tracker turns that recipe into a measurement layer. A few dozen prompts, a weekly run, and a SQLite roll-up give you a citation-rate trend to report on. The domain list also shows which competitor content Perplexity treats as authoritative.

If you came for "use Perplexity to scrape," `extraction_prompt` does the same job in one Scrapfly call. The Perplexity API stays valid for many readers, but it's not the right shape for fetch-plus-parse pipelines. Scrapfly covers both flows from one account.



Legal Disclaimer and PrecautionsThis tutorial covers popular web scraping techniques for education. Interacting with public servers requires diligence and respect:

- Do not scrape at rates that could damage the website.
- Do not scrape data that's not available publicly.
- Do not store PII of EU citizens protected by GDPR.
- Do not repurpose *entire* public datasets which can be illegal in some countries.

Scrapfly does not offer legal advice but these are good general rules to follow. For more you should consult a lawyer.

 

   Table of Contents















 

  Table of Contents- [Key Takeaways](#key-takeaways)
- [Are You Trying to Scrape Perplexity AI, or Use Perplexity to Scrape?](#are-you-trying-to-scrape-perplexity-ai-or-use-perplexity-to-scrape)
- [Why Scrape Perplexity AI?](#why-scrape-perplexity-ai)
- [What Data Can You Scrape from Perplexity?](#what-data-can-you-scrape-from-perplexity)
- [Project Setup](#project-setup)
- [How to Submit a Perplexity Query](#how-to-submit-a-perplexity-query)
- [How to Scrape Perplexity Search Results](#how-to-scrape-perplexity-search-results)
- [Configuring the Scrapfly Request](#configuring-the-scrapfly-request)
- [Opening the Query URL and Optional UI Actions](#opening-the-query-url-and-optional-ui-actions)
- [Detecting When the Streaming Response Completes](#detecting-when-the-streaming-response-completes)
- [Extracting Answers and Citations with extraction\_prompt](#extracting-answers-and-citations-with-extraction-prompt)
- [Bypass Perplexity Blocking with Scrapfly](#bypass-perplexity-blocking-with-scrapfly)
- [Power your scraping with Scrapfly](#power-your-scraping-with-scrapfly)
- [How Do You Build a Perplexity Citation Tracker?](#how-do-you-build-a-perplexity-citation-tracker)
- [FAQ](#faq)
- [Summary](#summary)
 
    Join the Newsletter  Get monthly web scraping insights 

 

  



Scale Your Web Scraping

Anti-bot bypass, browser rendering, and rotating proxies, all in one API. Start with 1,000 free credits.

  No credit card required  1,000 free API credits  Anti-bot bypass included 

 [Start Free](https://scrapfly.io/register) [View Docs](https://scrapfly.io/docs/onboarding) 

 Not ready? Get our newsletter instead. 

 

## Explore this Article with AI

 [ ChatGPT ](https://chat.openai.com/?q=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-perplexity) [ Gemini ](https://www.google.com/search?udm=50&aep=11&q=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-perplexity) [ Grok ](https://x.com/i/grok?text=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-perplexity) [ Perplexity ](https://www.perplexity.ai/search/new?q=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-perplexity) [ Claude ](https://claude.ai/new?q=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-perplexity) 



 ## Related Articles

 [  

 blocking 

### How to Bypass Cloudflare When Web Scraping in 2026

Cloudflare offers one of the most popular anti scraping service, so in this article we'll take a look how it works and h...

 

 ](https://scrapfly.io/blog/posts/how-to-bypass-cloudflare-anti-scraping) [  

 python project 

### How to Build a Price Tracker Using Python

A complete walkthrough for building a single-site price tracker in Python: async scraping with httpx and parsel, durable...

 

 ](https://scrapfly.io/blog/posts/how-to-build-a-price-tracker-in-python) [     

 python blocking 

### How Cloudflare Detects Bots: TLS, HTTP/2, Canvas, and Turnstile Explained

Learn how Cloudflare detects bots using TLS, HTTP/2, Canvas, WebGL, behavioral analysis, and Turnstile, plus how to scra...

 

 ](https://scrapfly.io/blog/posts/how-cloudflare-detects-bots) 

  ## Related Questions

- [ Q How to capture background requests and responses in Playwright? ](https://scrapfly.io/blog/answers/how-to-capture-xhr-requests-playwright)
 
  



   



 Scale your web scraping effortlessly, **1,000 free credits** [Start Free](https://scrapfly.io/register)