Overview

Scraping

Extract content and structured data from web pages

Quick Start#

from pydantic import BaseModel
from notte_sdk import NotteClient
 
class HackerNewsPost(BaseModel):
    title: str
    url: str
    points: int
    author: str
 
class HackerNewsFeed(BaseModel):
    posts: list[HackerNewsPost]
 
client = NotteClient()
 
result = client.scrape(
    url="https://news.ycombinator.com",
    response_format=HackerNewsFeed,
    instructions="Extract the top 5 posts from the front page"
)
 
for i, post in enumerate(result.data.posts, 1):
    print(f"{i}. {post.points} - {post.title}")

Scraping Methods#

Notte provides two ways to scrape:

Method Use Case
client.scrape(url) Quick, one-off scrapes
session.scrape() Scraping after navigation or authentication

Quick Scrape#

client = NotteClient()
 
# Returns markdown content
markdown = client.scrape("https://example.com")

Session-Based Scrape#

For scraping after authentication or navigation:

with client.Session() as session:
    session.execute(type="goto", url="https://example.com/login")
    session.execute(type="fill", selector="input[name='email']", value="user@example.com")
    session.execute(type="fill", selector="input[name='password']", value="password")
    session.execute(type="click", selector="button[type='submit']")
 
    session.execute(type="goto", url="https://example.com/dashboard")
 
    content = session.scrape()

Structured Extraction#

Extract data into typed objects using Pydantic models (Python) or Zod schemas (JavaScript). The extraction is powered by an LLM that understands the page content and extracts the specified fields.

Using Pydantic Models#

from pydantic import BaseModel
 
class Product(BaseModel):
    name: str
    price: float
    description: str
 
client = NotteClient()
product = client.scrape(
    "https://example.com/product", response_format=Product, instructions="Extract the product details"
)
 
print(f"Name: {product.name}, Price: {product.price}")

Using Instructions Only#

For flexible extraction without a strict schema:

result = client.scrape(
    "https://example.com/article", instructions="Extract the article title, author, and publication date"
)

Extracting Lists#

class Article(BaseModel):
    title: str
    url: str
    summary: str
 
class ArticleList(BaseModel):
    articles: list[Article]
 
articles = client.scrape(
    "https://news.example.com", response_format=ArticleList, instructions="Extract all articles from the homepage"
)

Nested Structures#

class Address(BaseModel):
    street: str
    city: str
    country: str
 
class Company(BaseModel):
    name: str
    description: str
    address: Address
    employee_count: int | None
 
company = client.scrape(
    "https://example.com/about", response_format=Company, instructions="Extract company information including address"
)

Image Extraction#

images = client.scrape("https://example.com/gallery", only_images=True)
 
for image in images:
    print(f"URL: {image.url}")
    print(f"Description: {image.description}")

Configuration Options#

Content Filtering#

# Only main content (excludes navbars, footers, sidebars) - Default
markdown = client.scrape(url, only_main_content=True)
 
# Include all page content
markdown = client.scrape(url, only_main_content=False)
markdown = client.scrape(url, scrape_links=True)   # Include links (default)
markdown = client.scrape(url, scrape_images=True)  # Include images (off by default)

Scoped Scraping#

with client.Session() as session:
    content = session.scrape(selector="article.main-content")
    content = session.scrape(selector="#product-details")

Return Types#

The scrape method returns different types based on parameters:

Parameters Return Type
None str (markdown)
instructions StructuredData[BaseModel]
response_format StructuredData[YourModel]
only_images=True list[ImageData]

Use Cases#

Data Collection#

class ProductInfo(BaseModel):
    name: str
    price: float
    rating: float | None
    reviews_count: int | None
 
urls = ["https://store.example.com/product/1", "https://store.example.com/product/2"]
 
products: list[ProductInfo] = []
for url in urls:
    data = client.scrape(url, response_format=ProductInfo)
    products.append(data)

Content Monitoring#

Track how a pricing page changes over time by scraping it on a schedule and diffing against the previous version.

Research and Analysis#

class ResearchPaper(BaseModel):
    title: str
    authors: list[str]
    abstract: str
    publication_date: str | None
    citations: int | None
 
result = client.scrape("https://papers.example.com/paper/123", response_format=ResearchPaper)

Best Practices#

1. Use Specific Instructions#

# Good
instructions = "Extract the product name, price in USD, and availability status"
 
# Vague
instructions = "Get product info"

2. Define Precise Schemas#

Match your schema to the actual page content, don't include fields the page might not have.

3. Handle Missing Data#

class Product(BaseModel):
    name: str
    price: float
    discount_price: float | None = None
    rating: float | None = None

4. Scope Your Scrapes#

with client.Session() as session:
    # Scrape only the main article, not comments or sidebar
    content = session.scrape(selector="article.main")

Next Steps#


Back to overview

Updated

Was this page helpful?