How to Get Perplexity Sources and Citations via API
If you need to scrape Perplexity sources — the ordered list of citations Perplexity shows above and inside every answer — you have three options: the official Perplexity API (which returns citations, but not the same ones the consumer product shows), a DIY headless-browser scraper against perplexity.ai (fragile, for reasons we'll get into), or a scraping API that runs your prompt through the real Perplexity interface and returns the answer plus every citation with its position as JSON.
Which one is right depends on a question most people skip: whose citations do you actually want — the developer API's, or the ones real users see? For GEO and brand-visibility work, it has to be the second. Here's the full picture.
Perplexity's official API vs the web UI: the citations differ
Perplexity does have an official developer API (the Sonar family of models), and it does return citations. If your use case is "give my app a search-grounded answer engine," use it — it's the sanctioned, stable path.
But the Sonar API is a developer model endpoint, not a window into the consumer product. The web and mobile apps run their own orchestration on top: their own model selection and system prompts, their own retrieval and source-ranking behaviour, plus interface features the API doesn't model at all — related follow-up questions, media panels, shopping modules. Ask the same question in the API and in the app and you will regularly get different answers citing different sources in a different order.
That gap is the whole problem for measurement use cases:
| Official Sonar API | Perplexity web UI | |
|---|---|---|
| What it is | Developer model endpoint | The consumer product |
| Citations | Yes, but its own retrieval | Yes — what users actually see |
| Related questions | Not an interface concept | Yes |
| Stability | Versioned, sanctioned | Changes whenever the product does |
| Right for | Building answer features | Measuring visibility & citations |
If you're tracking whether your domain gets cited when a buyer researches your category, the web UI's citation list is the ground truth. Users don't see API responses.
What a Perplexity answer actually contains
Perplexity is the most citation-heavy of the major AI search engines — nearly every sentence is attributable, which makes it the clearest window into how AI systems choose sources. A single answer page carries:
- The answer text itself, with inline citation markers.
- Sources: an ordered list of cited pages — title, URL, and position. Position matters: being source #1 versus source #8 is the closest thing AI search has to ranking.
- Related questions: the follow-ups Perplexity suggests, which are effectively free query-expansion data for your keyword research.
- Depending on the query: media results, shopping modules, and other interface panels.
For GEO purposes, sources and their order are the money data, and relatedQuestions is the underrated bonus.
The DIY route: scraping perplexity.ai yourself
Being transparent about what this takes, because for small one-off experiments it's genuinely an option.
You'd use Playwright or Puppeteer: load perplexity.ai, submit a query, wait for the streamed answer to complete, then parse sources out of the DOM. The recurring pain points:
- Streaming answers. Like ChatGPT, Perplexity streams responses. Your scraper must reliably detect when the answer — and the source list, which can populate separately — is finished. Grab too early and you get partial citations.
- Rotating layouts. Perplexity ships interface changes frequently, and answer layouts vary by query type (a shopping query renders differently from an informational one). Every variant is another parser branch, and every redesign breaks some of them.
- Rate limits and bot defenses. Sustained automated traffic from one IP gets throttled or challenged. Scale means proxy rotation and fingerprint management — the standard anti-bot arms race.
- Position fidelity. The part people get wrong: extracting which citation maps to which position, across layout variants, is much harder than extracting a bag of URLs. And position is the data point you care about.
A weekend project handles 50 queries. A production GEO tool running thousands of prompts daily across markets is a different animal — you're now operating browser infrastructure as a second job.
The API route: Perplexity sources as structured JSON
llmdata's Perplexity endpoint runs your prompt against the real Perplexity interface and returns the parsed result. One request:
curl -X POST https://api.llmdata.dev/v1/monitor/perplexity \
-H "Authorization: Bearer $LLMDATA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "top CRM software for small business",
"country": "US",
"include": { "sources": true, "relatedQuestions": true }
}'
And the response:
{
"success": true,
"result": {
"text": "The top CRM options for small businesses are...",
"sources": [
{ "title": "...", "url": "https://...", "position": 1 },
{ "title": "...", "url": "https://...", "position": 2 }
],
"relatedQuestions": ["What is the cheapest CRM?"],
"entities": ["HubSpot", "Pipedrive", "Zoho"]
}
}
Every source arrives with its position, so you can track citation rank over time rather than just presence. The country parameter runs the prompt from the region you specify — Perplexity's answers and sources vary by market, and measuring only from your own location quietly skews the data. The entities array gives you the brands named in the answer without running your own NER, which is what you'll diff to catch a competitor displacing you.
Build a "who does Perplexity cite for my keywords" report
Here's the practical payoff — a citation share-of-voice report in about 40 lines of Python:
import requests
from collections import Counter, defaultdict
from urllib.parse import urlparse
API_KEY = "..." # your llmdata key
PROMPTS = [
"top CRM software for small business",
"best CRM for startups",
"hubspot alternatives for small teams",
]
MY_DOMAIN = "example.com"
domain_counts = Counter()
positions = defaultdict(list)
for prompt in PROMPTS:
r = requests.post(
"https://api.llmdata.dev/v1/monitor/perplexity",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"prompt": prompt,
"country": "US",
"include": {"sources": True, "relatedQuestions": True},
},
)
data = r.json()
if not data.get("success"):
continue
for src in data["result"].get("sources", []):
domain = urlparse(src["url"]).netloc.removeprefix("www.")
domain_counts[domain] += 1
positions[domain].append(src["position"])
total = sum(domain_counts.values())
print(f"{'domain':<30} {'cites':>5} {'share':>7} {'avg pos':>8}")
for domain, n in domain_counts.most_common(15):
avg = sum(positions[domain]) / len(positions[domain])
marker = " <-- you" if domain == MY_DOMAIN else ""
print(f"{domain:<30} {n:>5} {n/total:>6.1%} {avg:>8.1f}{marker}")
Run this daily on a schedule and store the results, and you have the core of an AI citation tracker: your citation share of voice, your average citation position, and the exact competing pages winning citations you want. The pages Perplexity cites repeatedly in your niche are worth reverse-engineering — format, freshness, structure — because they're your actual competition in AI search.
Two upgrades worth making early:
- Repeat runs. AI answers are non-deterministic; the source list shifts between runs. Query each prompt several times per window and report citation rates, not one-off snapshots.
- Harvest
relatedQuestions. Feed them back into your prompt list. Perplexity is telling you, for free, how queries in your niche fan out.
Why GEO tools need the web-UI view
Worth stating as its own principle: measure the surface your audience uses. A brand-visibility score built on developer-API responses measures a product no buyer touches. Everything downstream — client reports, share-of-voice trends, content decisions — inherits that flaw. The web interface is the ground truth, which is why the harder-to-get dataset is the one worth getting.
This principle extends across engines. The same divergence exists between the OpenAI API and the ChatGPT web product — covered in depth in how to scrape ChatGPT responses — and between Google's developer APIs and what Google AI Overviews actually render on the results page. llmdata's endpoints all target the consumer surfaces, with the same response schema, so a cross-engine citation tracker is mostly the same code with a different URL. ChatGPT responses even include the web searches the model ran, which pairs well with Perplexity's related questions for query-expansion research.
Getting started
The workflow that works: pick 20–50 prompts that mirror how buyers research your category, run them daily against Perplexity with repeat sampling, store the sources arrays, and report citation share and average position weekly. Everything fancy comes later; this alone puts you ahead of teams still screenshotting answers.
llmdata is in early access — if you want Perplexity citations (plus ChatGPT, Gemini, Grok, Copilot and Google's AI surfaces) as clean JSON from one API, join the early access.