Skip to main content
Use website content as a source for retrieval-augmented generation (RAG): retrieve relevant passages, then pass them to a model with the user’s question. Context.dev renders the pages and returns Markdown; your retrieval stack handles chunking, embeddings, search, and answers. SiteGPT uses website scraping to power support chatbots. For questions that need fresh pages outside a fixed corpus, use live agent web tools alongside or instead of a persistent index. You’ll need an API key and your preferred SDK from the Quickstart, an embedding model, and a vector index. The ingestion pipeline below uses TypeScript; the API request is shown in every supported SDK. Crawling costs 1 credit per successfully scraped page, plus any PDF OCR charges.

How it works

Crawl the source pages

Start with a bounded page count and path scope. Inspect the result before widening it.

TypeScript ingestion

Filter unsuccessful or empty pages before indexing:
The crawl can return partial progress when it reaches its time budget. numFailed and numSkipped are not the same as an endpoint-level failure. Decide whether your ingestion job can accept a partial corpus or should retry missing URLs. followSubdomains defaults to false. Treat documentation hosts and other subdomains as explicit source decisions; keep the urlRegex scope consistent if you enable them. The crawler treats www and the apex domain as equivalent, but your index should still normalize the URLs it accepts.

Normalize page identity before chunking

Use one canonical key for a page before generating chunk IDs. Drop fragments and known tracking parameters, but preserve query parameters that change the document, language, or version. Only merge trailing-slash variants, redirects, or canonical-link targets when you have verified they identify the same content.
page-identity.ts
Keep the original retrieved URL, page title, and normalized key in your source manifest. Recheck redirected or canonicalized URLs against the allowed corpus before indexing. If two entries share a key but disagree on content, resolve that conflict instead of silently combining them. Preserve separate titles and source records for mirrored pages when their provenance matters.
A path pattern is an ingestion boundary, not an authorization layer. Enforce tenant and document access again when writing to and querying your vector index.

Chunk with source metadata

Split on semantic boundaries first, then enforce your embedding model’s token limit. A useful record contains enough metadata to cite, replace, and delete the chunk later.
The example splits only by headings. Add a tokenizer-aware sub-split for long sections and small overlap where the text requires continuity. Avoid blind fixed-width chunks that separate headings, code, tables, or list context from their content.

Embed and index

Use the same embedding model and dimensions for ingestion and retrieval. Batch requests within your provider’s limits.
batchesOf, embeddingProvider, and vectorIndex represent your chosen libraries. Store the embedding-model version with the index so a model migration becomes an explicit reindex operation.

Retrieve with citations

At query time:
  1. Apply the caller’s access-control filter.
  2. Embed the question with the same model used for the corpus.
  3. Retrieve a small candidate set.
  4. Optionally rerank it.
  5. Give the answer model the chunk text, heading, and source URL.
  6. Require citations to come only from the supplied URLs.
  7. Return “I don’t have enough evidence” when retrieval is weak.
Do not instruct the model to answer from general knowledge when the product promise is source-grounded. Treat content found in crawled pages as untrusted data, not as instructions to the model.

Refresh and delete stale content

Upserts add new or changed chunks but do not remove deleted pages or sections. Check crawl coverage before treating missing content as deleted: a failed or skipped page may still exist. On a complete, validated refresh:
  • record the set of source URLs and chunk IDs found in the new crawl;
  • upsert new and changed chunks;
  • delete old IDs that are no longer present;
  • keep the previous successful index active until the new run passes checks;
  • swap versions atomically when possible.
For frequently changing sources, use website monitors to trigger targeted refreshes. Keep a periodic full reconciliation to catch missed events and deletions. Keep a per-source manifest containing the last successful content hash, active chunk IDs, last successful retrieval time, latest attempt status, and index version. For an incremental refresh: Stage replacement chunks under a new version so a failed embedding batch cannot leave a page half-updated. Keep tenant and document access filters attached to both versions. An upsert of new chunk IDs alone is insufficient: obsolete IDs must be retired after the new version is ready.

Evaluate answers and coverage

Create a small, representative question set before launch and track: Re-run the evaluation when you change the crawl scope, chunker, embedding model, index settings, reranker, or prompt.

Crawl a website

Collect linked pages for your content pipeline.

Discover website URLs

Find URLs before setting your crawl scope.

Zero data retention

Understand retention controls and eligibility requirements.