r/LocalLLaMA 2026 has regular threads on pairing local uncensored models (Dolphin, Wizard, Nous) with a cloud-hosted scraping backend. The split is deliberate: the LLM runs locally for privacy and flexibility, Scavio supplies the web data. This tutorial builds that architecture. Scavio's Extract endpoint (POST /api/v1/extract) reads a URL and returns it as Markdown, HTML or plain text, so the local model works on clean page content instead of raw markup. Use mode advanced for pages built with JavaScript, and the Crawl endpoint when you need a whole site rather than one page.
API Docs: Extract API, Crawl API
Prerequisites
- Ollama or llama.cpp
- A local uncensored model (dolphin-mixtral, nous-hermes)
- A Scavio API key
- Python 3.10+
Walkthrough
Step 1: Run the local LLM
Ollama makes this one command.
ollama run dolphin-mixtralStep 2: Call Scavio for the scraping layer
Scavio returns the data, so there is no fetching layer for you to maintain.
import requests, os
# Scavio Extract reads one URL and returns the page as markdown, html or text.
# mode: "normal" (1 credit), "advanced" renders JavaScript (1 credit),
# "ultra" for the hardest pages (2 credits). Only a successful call is billed.
# Docs: https://scavio.dev/docs/extract
def scavio_extract(url, headers, mode="normal", fmt="markdown"):
r = requests.post("https://api.scavio.dev/api/v1/extract", headers=headers,
json={"url": url, "format": fmt, "mode": mode}, timeout=90)
r.raise_for_status()
return r.json()["data"]["content"]
API_KEY = os.environ['SCAVIO_API_KEY']
def fetch(url, mode='normal'):
return scavio_extract(url, {'Authorization': f'Bearer {API_KEY}'}, mode=mode)Step 3: Let the local LLM do extraction
No content filters on the extraction prompt.
import requests
def extract_with_local(html, instruction):
r = requests.post('http://localhost:11434/api/generate',
json={'model': 'dolphin-mixtral', 'prompt': f'{instruction}\n\nPAGE:\n{html[:4000]}'})
return r.json()['response']Step 4: Wire the full pipeline
Fetch via Scavio, extract via local LLM.
def scrape(url, instruction):
html = fetch(url)
return extract_with_local(html, instruction)
print(scrape('https://target.com', 'Extract all product names and prices as JSON.'))Step 5: Validate output
Light schema check before saving.
import json
def validate(out):
try: json.loads(out); return True
except: return FalsePython Example
import os, requests
# Scavio Extract reads one URL and returns the page as markdown, html or text.
# mode: "normal" (1 credit), "advanced" renders JavaScript (1 credit),
# "ultra" for the hardest pages (2 credits). Only a successful call is billed.
# Docs: https://scavio.dev/docs/extract
def scavio_extract(url, headers, mode="normal", fmt="markdown"):
r = requests.post("https://api.scavio.dev/api/v1/extract", headers=headers,
json={"url": url, "format": fmt, "mode": mode}, timeout=90)
r.raise_for_status()
return r.json()["data"]["content"]
API_KEY = os.environ['SCAVIO_API_KEY']
def scrape(url, instruction):
html = scavio_extract(url, {'Authorization': f'Bearer {API_KEY}'})
r = requests.post('http://localhost:11434/api/generate',
json={'model': 'dolphin-mixtral', 'prompt': f'{instruction}\n\n{html[:4000]}'})
return r.json().get('response', '')
print(scrape('https://example.com', 'List headings as JSON'))JavaScript Example
const API_KEY = process.env.SCAVIO_API_KEY;
export async function scrape(url, instruction) {
const s = await fetch('https://api.scavio.dev/api/v1/extract', {
method: 'POST',
headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ url, format: 'markdown', mode: 'normal' })
});
const page = (await s.json()).data?.content || '';
const o = await fetch('http://localhost:11434/api/generate', {
method: 'POST',
body: JSON.stringify({ model: 'dolphin-mixtral', prompt: `${instruction}\n\n${page.slice(0, 4000)}`, stream: false })
});
return (await o.json()).response;
}Expected Output
Fully local extraction logic, with Scavio supplying the web data. Per-page cost: 1 Scavio credit + local GPU time. Data never leaves local box except the URL.