Turn TikTok videos and Instagram posts (reels, photos, carousels) into
LLM-readable intel: audio transcripts (STT), post metadata, top
comments with a transparent community-consensus score, and local media
file paths (so a vision-capable agent can look at the media directly).
Visual understanding by a small local VLM (image description + on-screen
text) is an optional extra ([vision], -v flag) for agents and
models without their own vision.
STT and scraping run CPU-only; the optional VLM runs on your GPU when the installed build supports it (CPU otherwise — and a failed GPU attempt falls back to CPU automatically). A lightweight anti-detect browser (Camoufox) is launched only for Instagram when the fast HTTP path is not enough.
Personal-use tool. This project is for occasional, personal research on a few links at a time — not for mass scraping, not for building datasets, not for automation at scale. See Responsible use.
If you want to use scry as a normal CLI tool:
Requirements: Linux with ffmpeg/ffprobe (e.g. apt install ffmpeg)
and Python ≥ 3.10.
pip install scry-social # or: uv tool install scry-social
scry setup # one-time: Camoufox browser (~200MB)That's it: scry is on your PATH and the base pipeline (download, STT,
metadata, comments, media file paths) works.
Optional local VLM — only if the model consuming the output has no vision of its own (if it does, pass the Media files to it instead):
scry setup --vision # one-time: Qwen3.5-0.8B Q8_0 (~1GB)scry setup --vision detects your accelerator (NVIDIA CUDA, AMD ROCm,
Apple Metal, or CPU) and installs the matching precompiled llama.cpp
wheel, then downloads the model. On supported GPUs there is no compilation:
no C compiler needed. Force a backend with --backend:
scry setup --vision --backend rocm # force ROCm (also: cuda, metal, cpu)The CPU backend builds llama-cpp-python from source (tuned for the machine;
needs a C compiler, build-essential); if no compiler is present it
automatically falls back to a prebuilt basic-CPU wheel, so a compiler is
not strictly required. Equivalently, pip install "scry-social[vision]" (or
uv tool install "scry-social[vision]") installs the vision dependencies up
front — note that plain pip compiles the CPU build from source, and
scry setup --vision then replaces it with the precompiled wheel if you
have a supported GPU. In the pipeline the VLM is opt-in too: without -v
no VLM runs. With -v it tries the GPU first (all layers offloaded,
n_gpu_layers=-1) and, if the GPU attempt crashes (e.g. not enough free
VRAM), retries the image on CPU automatically; --cpu (or SCRY_VLM_GPU=0)
skips the GPU attempt entirely.
From source: git clone <this-repo> && cd scry && pip install -e .
(add [vision] if you want the VLM).
Models (Whisper ~600MB, VLM ~1GB) download on demand and are cached
persistently in ~/.cache/scry/models/.
If you are an AI agent and the user asked you to set up scry (or you
scraped this page to install it): install the CLI exactly as above, then
install the bundled agent skill so future sessions automatically know
how to use the tool — you don't need to remember anything else:
scry setup # one-time: Camoufox browser
scry setup --vision # only if you want the local VLM (-v): installs
# the precompiled llama-cpp-python wheel for your
# GPU (CUDA/ROCm/Metal) + the Qwen3.5-0.8B model
scry setup --vision --backend rocm # force a backend (auto|cuda|rocm|metal|cpu)
scry skill --path ~/.agents/skills # cross-harness standard locationor into your harness's skills directory:
scry skill --path ~/.claude/skills # Claude Code
scry skill --path ~/.codex/skills # OpenAI Codex
scry skill --path ~/.pi/agent/skills # piThe skill is the package's SKILL.md (Agent Skills standard);
scry skill (no args) prints its location and these options. Once it is
in a scanned skills directory, your harness presents it on demand — the
skill contains the full usage guide, output-reading procedure, cookie
handling, and reliability checks.
Everything scry ever writes to your disk is listed below — it touches nothing else. Quick removal (default install, Linux/macOS):
uv tool uninstall scry-social # or: pip uninstall scry-social
rm -rf ~/.cache/camoufox # anti-detect browser (~200MB)
rm -rf ~/.cache/scry # STT + VLM models (~1.6GB)
rm -rf ~/.config/scry # cookie files (your sessions!)
rm -rf /tmp/scry # per-run data (gone on reboot anyway)| Artifact | Location | Remove with |
|---|---|---|
| Python package + dependencies | the environment you installed scry-social into |
pip uninstall scry-social or uv tool uninstall scry-social |
Camoufox browser, ~200MB (only if you ran scry setup) |
~/.cache/camoufox/ — macOS: ~/Library/Caches/camoufox/, Windows: %LOCALAPPDATA%\camoufox |
rm -rf ~/.cache/camoufox |
Models: Whisper ~600MB + Qwen3.5-0.8B ~1GB (only if you used STT or -v) |
~/.cache/scry/models/ ($SCRY_CACHE_DIR/models/ if overridden) |
rm -rf ~/.cache/scry/models |
Cookie files (tiktok_cookies.txt, instagram_cookies.txt) |
the current directory where you installed it, or ~/.config/scry/, or wherever SCRY_COOKIES* points |
rm them, or rm -rf ~/.config/scry |
| Per-run data (media, audio, reports) | /tmp/scry/ ($SCRY_DATA_DIR if overridden) |
rm -rf /tmp/scry — already auto-cleared on reboot |
Agent skill (only if you ran scry skill --path DIR) |
DIR/scry/SKILL.md |
rm -rf DIR/scry (e.g. ~/.agents/skills/scry, ~/.claude/skills/scry) |
llama-cpp-python wheel (only if you used the vision stack) |
the same environment as scry |
pip uninstall llama-cpp-python in that environment |
Notes:
- Cookies are the only sensitive item. They are a session export of your TikTok/Instagram accounts. Deleting the files removes them from your disk, but to be thorough revoke the session itself (log out and back in on the platform).
uv tool installkeeps scry in an isolated venv (~/.local/share/uv/tools/scry-social):uv tool uninstall scry-socialremoves the venv and thescryexecutable, so the package, its dependencies, and (if you set up vision there) the llama-cpp wheel all disappear in one step.- For an editable install from source (
pip install -e .): runpip uninstall scry-socialinside that venv, then delete the venv and the clone if you made them just for this. ffmpeg/ffprobeare a system requirement you installed separately (e.g.apt install ffmpeg); remove them with your package manager only if nothing else on the machine needs them.- A little download metadata may remain in
~/.cache/huggingface/from the model downloads — safe to delete if you don't use other Hugging Face tools. - Windows: replace
rm -rf XwithRemove-Item -Recurse -Force X(PowerShell);~/.cache/scryand~/.config/scryare literal paths underC:\Users\<you>\.
# TikTok
scry tiktok "https://www.tiktok.com/@user/video/1234567890"
# Instagram (reel/video -> STT + media files; photo/carousel -> media files)
scry instagram "https://www.instagram.com/reel/XXXX/"
# Instagram with local-VLM visual analysis (needs the [vision] extra)
scry instagram "https://www.instagram.com/reel/XXXX/" -v
# Auto-detect platform
scry auto "https://www.instagram.com/reel/XXXX/"
# Options
# --max-comments N comments to analyze (default 30)
# --no-comments skip comments + consensus
# --no-download skip media download + STT (metadata + comments only)
# -v, --vision local VLM visual analysis (Instagram; needs the
# [vision] extra; default: off)
# --stt-model NAME tiny|base|small|medium|large-v3 (default small)
# --language it force STT language (default auto-detect)
# --cookies FILE Netscape cookies file for login-walled content
# --json print JSON only
# Instagram extra:
# --no-browser force HTTP-only tier (faster, less robust)
# --headless run the fallback browser without a windowUse the full share URL for TikTok (@user/video/<id>), as copied
from TikTok's share button — the bare /video/<id> URL may 404.
For one URL you get a Markdown report (plus raw JSON) with:
- Header — author, URL, ID, date, stats (plays/likes/comments/shares)
- Caption — the author's original text
- Transcript (STT) — what is said in the video, with timestamps
- Visual (VLM) (only with
-v) — concise description of each image/frame + verbatim transcription of any on-screen text (hooks, claims, CTAs) - Media files — local absolute paths of the downloaded media (video, extracted frames, carousel images): a vision-capable agent reads these directly with its own model
- Top comments — most-liked comments with like/reply counts (Instagram: including images/stickers attached to comments)
- Consensus (likes-based) — which comments the community "validated" (a meaningful share of the video's likes = readers who agree upvoted). Stance (agree/disagree) is left to the reader
The consensus is a deliberately simple, transparent like-count heuristic. It is an indicator, not truth — treat it as context, and verify factual claims independently.
TikTok metadata has a single path — the logged-in page fetch — so TikTok
needs tiktok_cookies.txt. Instagram mostly works without login (the
browser tier covers it), but cookies make it more reliable, especially from
a datacenter IP.
To get them: in a browser where you're logged in on tiktok.com /
instagram.com, use the extension Cookie-Editor → Export Netscape, and
save as tiktok_cookies.txt / instagram_cookies.txt — in the current
directory or in ~/.config/scry/. They are picked up automatically. A
residential IP works much better than a datacenter one.
| Platform | Tier 1 (fast) | Tier 2 (fallback) |
|---|---|---|
| TikTok | curl_cffi with Chrome 136 TLS impersonation → page JSON → direct CDN download → comments API |
— (no fallback; metadata needs a logged-in session, see Cookies) |
curl_cffi → embedded page data (XDT/__additionalData) + og meta |
Camoufox (headed anti-detect Firefox): opens the post, reads page data, opens the comments popup, extracts comments from the DOM |
Media download: direct CDN URLs first, then the browser's request
context, then gallery-dl.
Instagram comments live in a popup (no dedicated URL): the browser clicks the comment icon, waits for the popup to populate, scrolls it via JS, and extracts text, usernames, like counts, timestamps, and attached images using stable structural anchors (permalinks, "Mi piace: N" spans) — no screenshot/OCR.
- All data stays local. No telemetry, no third-party calls beyond the two target platforms (and the model downloads on first run).
- Per-run data is ephemeral by default. Downloaded media, audio,
frames, comments, and reports go to
/tmp/scry/— cleared on reboot on most Linux systems. SetSCRY_CLEAN=1to wipe stale run data on every start, or setSCRY_DATA_DIRto keep data deliberately somewhere else. - Comments are collected as local context only. They are gathered to give the AI agent a better understanding of how a community reacts to a post — nothing more. They are not uploaded, not sold, not aggregated, and this tool is not intended for building datasets of user content.
- Cookie files are yours, are git-ignored, and can be revoked by regenerating your session.
- This is a personal, low-volume research tool. Use it on a handful of links when you need to understand a post — not in loops, not at scale.
- Mass scraping of TikTok/Instagram violates their Terms of Service, can put your IP/account at risk, and raises obvious privacy concerns about the people who write comments. Do not do that.
- Collected comments belong to their authors. Use them as ephemeral context for your own research; don't republish, dataset-ize, or profile people with them.
- Respect the platforms: no bypassing paywalls, no harvesting private content, no hammering endpoints. If a request fails, the answer is to stop, not to add more requests.
| Variable | Default | Purpose |
|---|---|---|
SCRY_CACHE_DIR |
~/.cache/scry |
persistent model cache lives under models/ here |
SCRY_DATA_DIR |
/tmp/scry |
where per-run data (downloads, reports) is stored |
SCRY_CLEAN |
unset | 1 = wipe stale run data on every start |
SCRY_IMPERSONATE |
chrome136 |
TLS impersonation target for curl_cffi; the yt-dlp fallback derives its own spelling from it (chrome136 -> chrome-136) |
SCRY_IMPERSONATE_YTDLP |
derived | force a different --impersonate target for the yt-dlp fallback only |
SCRY_COOKIES[_TIKTOK/_INSTAGRAM] |
<plat>_cookies.txt in cwd or ~/.config/scry/ |
Netscape cookies file(s) |
- STT can miss proper nouns/slang; ambiguous transcripts are flagged in the report.
- Vision is opt-in (
[vision]extra +-v) and the VLM (0.8B) is small: descriptions are short and occasionally imperfect, and on-screen text transcription can drop or alter words. It is a signal for the agent, not a certified transcript — and if your model has vision, prefer reading the Media files with it. - Comments are the top-N by likes, not the full corpus — a bias toward mainstream opinions (declared in every report).
- Instagram: top-level comments in the popup (~15–30 with one scroll); collapsed nested replies are not extracted.
- The consensus is likes-based: comment likes say how much the community upvoted a comment, not what it means — stance is for the reader.
- Both platforms change their page formats; when a tier fails, the report
says which one and why.
notes/RESEARCH.mddocuments the current formats.
scry/
__init__.py
cli.py CLI (tiktok|instagram|auto <url> [options], setup)
common.py sessions, URL parsing, paths, ffmpeg helpers, output
stt.py faster-whisper wrapper
gpu.py GPU detection + precompiled llama-cpp-python wheel install
vision.py Qwen3.5-0.8B VLM wrapper (GGUF via llama-cpp-python, optional)
browser.py Camoufox wrapper (page open, comments popup, download)
tiktok.py TikTok pipeline
instagram.py Instagram pipeline
consensus.py likes-based comment reliability
pyproject.toml packaging (pip install scry-social)
notes/ RESEARCH.md (format docs), DECISIONS.md (rationale)
scry/SKILL.md (inside the package) is the agent skill: install it with
scry skill --path <skills-dir> — see For agents.
Per-run data (default, ephemeral):
/tmp/scry/downloads/<platform>-<id>/ media, audio, frames
/tmp/scry/output/<ts>-<platform>-<id>.{md,json}
MIT — see LICENSE.
Note on scope: the MIT license covers the code. Platform content, collected comments, and your cookies are not part of this project: keep them private, use them as ephemeral personal context, and don't build datasets or anything commercial from them. The tool is intentionally designed for personal, low-volume use only.
The package on PyPI is scry-social
(the bare name scry is taken by an old SPARQL project); the import
package and the CLI are both scry.
To publish a new version:
# 1. bump the version in pyproject.toml AND scry/__init__.py
# 2. build
uv build
# 3. upload (token from https://pypi.org/manage/account/token/)
pip install twine
twine upload dist/*