Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ Read more about E2B on the [E2B website](https://e2b.dev) and the official [E2B
- Upload dataset and analyze it with Llama 3 - [Python](./examples/upload-dataset-code-interpreter)
- Scrape Airbnb and analyze data with Claude 3 Opus and Firecrawl - [TypeScript](./examples/firecrawl-scrape-and-analyze-airbnb-data)
- Visualize website topics with Claude 3.5 Sonnet and Firecrawl - [Python](./examples/claude-visualize-website-topics)
- Search the web with the Perplexity Search API and analyze results in a sandbox - [Python](./examples/perplexity-search-python) / [TypeScript](./examples/perplexity-search-js)
- Next.js app with LLM + Code Interpreter and streaming - [TypeScript](./examples/nextjs-code-interpreter)
- How to run a Docker container in E2B - [Python/TypeScript](./examples/docker-in-e2b)
- How to run Playwright in E2B - [TypeScript](./examples/playwright-in-e2b)
2 changes: 2 additions & 0 deletions examples/perplexity-search-js/.env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
E2B_API_KEY=your_e2b_api_key
PERPLEXITY_API_KEY=your_perplexity_api_key
49 changes: 49 additions & 0 deletions examples/perplexity-search-js/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Perplexity Search + E2B Sandbox (TypeScript)

Use the [Perplexity Search API](https://docs.perplexity.ai/docs/search/quickstart) to fetch web sources, then analyze them inside an [E2B Sandbox](https://e2b.dev) with Python.

## What it does

1. Calls `POST https://api.perplexity.ai/search` with a query and optional filters (`max_results`, `search_domain_filter`, `search_recency_filter`).
2. Spawns an E2B sandbox and writes the JSON results to a file inside it.
3. Runs Python in the sandbox to count top domains and print result summaries.

## Prerequisites

- Node.js 18+
- An [E2B API key](https://e2b.dev/dashboard?tab=keys)
- A [Perplexity API key](https://www.perplexity.ai/account/api/keys)

## Setup

```bash
cp .env.template .env
# fill in E2B_API_KEY and PERPLEXITY_API_KEY (PPLX_API_KEY is also accepted)
npm install
```

## Run

```bash
npm start
# or with a custom query:
npm start -- "OpenAI DevDay 2026 announcements"
```

## Search options

The `perplexitySearch` helper in `index.ts` supports:

| Field | Type | Notes |
| ----------------------- | ----------------------------------------------------- | -------------------------------------------------------------------------------------- |
| `query` | `string` | Required. |
| `max_results` | `number` | Default 10. Set explicitly to bound results. |
| `search_domain_filter` | `string[]` | Allowlist (`"nytimes.com"`) **or** denylist (`"-pinterest.com"`). Don't mix the two. |
| `search_recency_filter` | `"hour" \| "day" \| "week" \| "month" \| "year"` | Restrict results to a recent time window. |

## API reference

- Search quickstart: https://docs.perplexity.ai/docs/search/quickstart
- Search API reference: https://docs.perplexity.ai/api-reference/search-post
- Domain filter docs: https://docs.perplexity.ai/docs/search/filters/domain-filter
- Date / recency filter docs: https://docs.perplexity.ai/docs/search/filters/date-time-filters
104 changes: 104 additions & 0 deletions examples/perplexity-search-js/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import 'dotenv/config'
import { Sandbox } from '@e2b/code-interpreter'

const PERPLEXITY_API_KEY =
process.env.PERPLEXITY_API_KEY || process.env.PPLX_API_KEY

if (!PERPLEXITY_API_KEY) {
throw new Error(
'Set PERPLEXITY_API_KEY (or PPLX_API_KEY). Get one at https://www.perplexity.ai/account/api/keys'
)
}

type SearchOptions = {
query: string
max_results?: number
search_domain_filter?: string[]
search_recency_filter?: 'hour' | 'day' | 'week' | 'month' | 'year'
}

type SearchResult = {
title: string
url: string
snippet: string
date?: string
}

async function perplexitySearch(opts: SearchOptions): Promise<SearchResult[]> {
const body: Record<string, unknown> = { query: opts.query }
if (opts.max_results !== undefined) body.max_results = opts.max_results
if (opts.search_domain_filter)
body.search_domain_filter = opts.search_domain_filter
if (opts.search_recency_filter)
body.search_recency_filter = opts.search_recency_filter

const res = await fetch('https://api.perplexity.ai/search', {
method: 'POST',
headers: {
Authorization: `Bearer ${PERPLEXITY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
})

if (!res.ok) {
const text = await res.text()
throw new Error(`Perplexity Search API ${res.status}: ${text}`)
}

const data = (await res.json()) as { results?: SearchResult[] }
return data.results ?? []
}

async function main() {
const query =
process.argv.slice(2).join(' ') || 'recent breakthroughs in quantum error correction'

console.log(`Searching Perplexity for: ${query}`)
const results = await perplexitySearch({
query,
max_results: 8,
search_recency_filter: 'month',
})
console.log(`Got ${results.length} results from Perplexity Search.`)

console.log('Spawning E2B sandbox to summarize results in-sandbox...')
const sandbox = await Sandbox.create()
try {
await sandbox.files.write(
'/home/user/results.json',
JSON.stringify(results, null, 2)
)

const execution = await sandbox.runCode(`
import json
from collections import Counter
from urllib.parse import urlparse

with open("/home/user/results.json") as f:
results = json.load(f)

print(f"Loaded {len(results)} results")
domains = Counter(urlparse(r["url"]).netloc for r in results)
print("Top domains:")
for domain, count in domains.most_common(5):
print(f" {domain}: {count}")

print("\\nTop result snippets:")
for r in results[:3]:
print(f"- {r['title']}\\n {r['url']}\\n {r.get('snippet', '')[:160]}\\n")
`)

console.log(execution.logs.stdout.join(''))
if (execution.logs.stderr.length) {
console.error(execution.logs.stderr.join(''))
}
} finally {
await sandbox.kill()
}
}

main().catch((err) => {
console.error(err)
process.exit(1)
})
Loading