Docs/API Reference/POST /v1/observe

POST /v1/observe Legacy

Main endpoint for web content extraction and element coordinate mapping. Routes requests to Reader or Geometry services based on mode.

Overview

Prefer the SDK: For AI agents, use the SDK Quick Start instead. The SDK provides better abstraction, action execution, and session management.

Base URL: https://api.sentienceapi.com/v1/observe

Authentication: Required - Bearer token in Authorization header

Request Parameters

Required Parameters

url (string) - The URL of the website to process. Must be a valid HTTP or HTTPS URL.

Optional Parameters

mode (string) - Specifies which service to use. Defaults to "read".

format (string) - Output format for read mode. Defaults to "markdown".

options (object) - Additional options for fine-tuning request behavior:

Request Examples

Read Mode (Markdown Extraction)

curl -X POST https://api.sentienceapi.com/v1/observe \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://news.ycombinator.com",
    "mode": "read",
    "format": "markdown",
    "options": {
      "contentLimit": 50000
    }
  }'

Map Mode (Performance - Default)

curl -X POST https://api.sentienceapi.com/v1/observe \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type": application/json" \
  -d '{
    "url": "https://news.ycombinator.com",
    "mode": "map"
  }'

Map Mode (Precision - Pixel Perfect)

curl -X POST https://api.sentienceapi.com/v1/observe \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type": application/json" \
  -d '{
    "url": "https://news.ycombinator.com",
    "mode": "map",
    "options": {
      "render_quality": "precision"
    }
  }'

Smart Filtering (95% Token Savings)

Reduce token costs dramatically on complex sites like Amazon, Slickdeals, or Reddit by intelligently selecting only the most important UI elements:

curl -X POST https://api.sentienceapi.com/v1/observe \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type": application/json" \
  -d '{
    "url": "https://www.amazon.com/s?k=laptop",
    "mode": "map",
    "options": {
      "limit": 100,
      "filter": {
        "min_area": 100,
        "allowed_roles": ["button", "textbox", "link"]
      }
    }
  }'

Result: Returns only the 100 most important interactive elements, reducing tokens from ~50,000 to ~2,500 (95% savings).

Visual Mode with Screenshot

curl -X POST https://api.sentienceapi.com/v1/observe \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type": application/json" \
  -d '{
    "url": "https://example.com/login",
    "mode": "visual",
    "options": {
      "screenshot_delivery": "url",
      "limit": 50
    }
  }'

Response Format

Read Mode Response

{
  "status": "success",
  "url": "https://news.ycombinator.com",
  "content": "# Hacker News\n\nStories:\n- AI breakthrough in reasoning\n- New framework release\n...",
  "title": "Hacker News",
  "description": "Hacker News new | past | comments | ask | show | jobs | submit",
  "credits_used": 1
}

Map Mode Response

{
  "status": "success",
  "url": "https://example.com",
  "viewport": { "width": 1920, "height": 1080 },
  "interactable_elements": [
    {
      "id": 0,
      "role": "button",
      "text": "Sign in",
      "bbox": { "x": 100, "y": 200, "width": 150, "height": 40 },
      "in_viewport": true,
      "is_occluded": false,
      "importance": 85,
      "visual_cues": {
        "background_color_name": "blue",
        "cursor_type": "pointer",
        "is_prominent": true
      }
    }
  ],
  "credits_used": 2
}

Visual Mode Response

{
  "status": "success",
  "url": "https://example.com/login",
  "viewport": { "width": 1920, "height": 1080 },
  "screenshot": {
    "type": "url",
    "url": "https://sentience-screenshots.s3.amazonaws.com/abc123.png",
    "format": "png",
    "size_bytes": 158277,
    "expires_at": "2025-12-20T05:10:45Z"
  },
  "interactable_elements": [
    {
      "id": 0,
      "role": "textbox",
      "text": "",
      "bbox": { "x": 500, "y": 300, "width": 300, "height": 40 },
      "attributes": { "placeholder": "Email" },
      "in_viewport": true,
      "is_occluded": false
    }
  ],
  "credits_used": 10
}

Response Fields

Common Fields (All Modes)

Read Mode Fields

Map/Visual Mode Fields

Visual Mode Exclusive Fields

Common ARIA Roles

Elements are ranked by importance. Higher priority roles receive higher importance scores:

High Priority (+1000 pts) - Form inputs:

Medium Priority (+500 pts) - Interactive controls:

Low Priority (+100 pts) - Content navigation:

Informational (0 pts) - Static content:

Best Practices

1. Use Smart Filtering on Complex Sites

For sites with hundreds of elements (Amazon, Reddit, news sites), use limit and filter:

{
  "options": {
    "limit": 100,
    "filter": {
      "min_area": 100,
      "allowed_roles": ["button", "textbox", "link"]
    }
  }
}

Result: 95% token reduction while keeping all important interactive elements.

2. Choose the Right Render Quality

3. Limit Content Length

For read mode, set contentLimit based on your needs:

{
  "options": {
    "contentLimit": 15000  // ~3,750 tokens
  }
}

4. Use Visual Cues Selectively

Enable include_visual_cues only when you need color/styling hints for icon-heavy UIs. It adds ~17 tokens per element.

Error Responses

{
  "status": "error",
  "error": "Invalid URL",
  "message": "The provided URL is not valid or cannot be accessed"
}

Common errors:

Credit Costs

ModeEngineCredits
ReadPerformance1
MapPerformance2
MapPrecision10
VisualPrecision (always)10

Migration to SDK

This endpoint is considered legacy. For new projects, use the Sentience SDK:

Benefits:

Quick comparison:

# Legacy API approach
import requests

response = requests.post(
    "https://api.sentienceapi.com/v1/observe",
    headers={"Authorization": "Bearer sk_..."},
    json={"url": "https://example.com", "mode": "map"}
)
elements = response.json()["interactable_elements"]

# SDK approach (recommended)
from sentience import SentienceBrowser, snapshot, find, click

with SentienceBrowser(api_key="sk_...") as browser:
    browser.page.goto("https://example.com")
    snap = snapshot(browser)
    button = find(snap, "role=button text~'submit'")
    click(browser, button.id)

Next Steps