> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pureframe.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Frame Map

> A visual 2D map of your entire video library, organized by visual similarity.

**Beta**

Frame Map projects every indexed frame in your library onto a 2D canvas, positioned by visual similarity — frames that look alike land close together. It's a way to browse a library visually instead of only through query search.

## In the app

Frame Map is available at [platform.pureframe.ai/framemap](https://platform.pureframe.ai/framemap).

* **Hover** a dot for a frame preview and video name
* **Click** a dot to pin it to the preview strip at the bottom
* **Double-click** to open the video at that timestamp
* **Lasso select** a region to inspect multiple frames at once
* **Click a cluster** in the sidebar to pin every frame in that cluster at once
* **Filter by collection** using the left panel

Frames are grouped into clusters automatically (HDBSCAN), each representing a visual theme — all your outdoor shots, all your whiteboard moments. Frames that don't fit any cluster show as uncategorized. Cluster quality improves with library size; at least 50 indexed videos is recommended for meaningful groupings.

## API access

```bash theme={null}
curl "https://api.pureframe.ai/v1/framemap?collection_id=col_abc123" \
  -H "Authorization: Bearer pf_..."
```

```json theme={null}
{
  "data": {
    "frames": [
      { "id": "frm_1", "x": 12.4, "y": -8.1, "video_id": "vid_abc", "collection_id": "col_abc123", "timestamp_start": 42.5, "thumbnail_url": "https://...", "cluster_id": 3 }
    ],
    "clusters": [
      { "id": 3, "label": "Whiteboard", "color": "#4f46e5", "frame_count": 128, "video_count": 6, "confidence": 0.82, "density": 4.1, "rank": 1 }
    ],
    "total_frames": 4211,
    "total_videos": 18,
    "total_collections": 1,
    "computed_at": "2026-07-20T02:00:00Z"
  }
}
```

Omit `collection_id` to compute the map across your whole account. The result is cached per scope (per collection, or globally) — repeat calls return the cached map instantly. Pass `force=true` to recompute after uploading new videos, which re-scans every frame vector and re-clusters from scratch, so it's slower and costs more than a cached read.

The Python SDK exposes this as `client.frame_map.get_framemap(...)`.
