Skip to content
Agentmart
Submit a tool

instagram

Search Instagram accounts, read profiles, and enumerate a profile's followers or following; find someone by name or handle.

Skill by overseers-desk

IndexedMIT★ 1
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/overseers-desk-instagram

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Search Instagram accounts, read profiles, and enumerate a profile's followers or following; find someone by name or handle. Also audits brand-account tag-reshare compliance.

Use cases: design, security

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/instagram

What's inside

Skill name
instagram
Description
Search Instagram accounts, read profiles, and enumerate a profile's followers or following; find someone by name or handle. Also audits brand-account tag-reshare compliance.
License
MIT
Instructions
240 lines in SKILL.md · view on GitHub

Agent Skills spec issues

  • name: "instagram" does not match folder "instagram.com"

Files (21)

  • SKILL.md
  • auth-audit-tag-reshares.tcl
  • auth-check-archived.tcl
  • auth-collab-expand.tcl
  • auth-fetch-followers.tcl
  • auth-fetch-post-comments.tcl
  • auth-fetch-recent-posts.tcl
  • auth-ig-inbox.tcl
  • auth-ig-posts.tcl
  • auth-ig-profile.tcl
  • auth-ig-thread.tcl
  • auth-inbox-noninvasive.tcl
  • auth-parse-search.tcl
  • auth-read-seen-thread.tcl
  • fbid-surface-selftest.tcl
  • ig-canonical.tcl
  • fetch-recent-posts.tcl · lib/
  • identity.tcl · lib/
  • ig-html.tcl · lib/
  • ig-profile.tcl · lib/
  • whoami.tcl

SKILL.md (first lines)

## Execution model

Spawn a **Sonnet subagent** to run the workflow. Each script runs under the **serialised-browsing** harness: `browser-serialiser` loads the skill into a policed safe interpreter and drives the browser through the command surface (no raw CDP, anti-ban pacing enforced). Invoke by reference, `browser-serialiser instagram.com/<script> <args>`; the subagent need not paste scripts inline. See the serialised-browsing skill for the command surface.

## Prerequisites

A logged-in Instagram session in the user-data-dir the serialiser targets.

Optional config, `[instagram.com] handle`: the account expected signed in. `browser-serialiser` names it in the `session missing` line it prints on exit 77, so a person reading a failed run knows which login to restore.

Note: `--lang` flags do not override Instagram's locale; it is a server-side account setting. The parsers are locale-agnostic, so this does not matter.

If a request redirects to `/accounts/login/` or returns empty JSON, the session has expired or been rate-limited. The harness classifies this as a terminal `logged-out`/`checkpoint` state and stops; let the user log in interactively before retrying.

## Pacing and walls

The harness owns pacing+jitter on every wire-touching verb and the 429/login backoff, so a script cannot burst. A profile view settles for a few seconds before the page-issued JSON is read; search reads the topsearch endpoint directly. On a 429 the harness backs off (capped) then goes terminal `rate-limited`; on a login/checkpoint redirect it goes terminal at once. A script never retries a wall.

## DM read-state policy

Before invoking any DM-content script (§9, and any future script whose filename carries `mark-seen`, `mutate-seen`, or `send`), name the specific thread(s) about to be touched and surface the read-state implication to the user, then wait for an explicit yes. For §9 the implication to surface is: this will only return content for threads already opened in the user's Instagram client; the script refuses unread threads and will not mark anything seen on the user's behalf.

§5 (`auth-inbox-noninvasive.tcl`) is exempt — it reads inbox metadata only, never thread content, and blocks seen-mutation requests at the Fetch layer.

The internal refusal gate inside §9 is a backstop. A run without prior disclosure violates the policy even if the script would have refused anyway.

## 1-2. Search accounts, hashtags and places

The script types the terms into the search page's box and reads the type-ahead results the page itself fetches, then prints the parsed report in one step:

```bash
browser-serialiser instagram.com/auth-parse-search SEARCH TERMS
```

Pass terms as plain arguments. The type-ahead response contains `users[]`, `hashtags[]`, and `places[]`. Each user includes `username`, `full_name`, `is_verified`, and (where applicable) a mutual-followers line, a useful signal for disambiguation. The output is a ranked list of candidate handles with display name, verified flag, profile URL, and mutual-followers context. Instagram's type-ahead matches handles more readily than spaced phrases: "summerlandcamels" finds `@summerlandcamels`, while "summerland camels" returned no users (2026-10-29). A run where the box fetched nothing is a fault, not an empty result.

The REST route `/web/search/topsearch/` answers Instagram's "Page Not Found" page (observed 2026-10-29), and the keyword results page (`/explore/search/keyword/`) lists posts, its accounts unit arriving empty.

## 3-4. Fetch and parse a profile

The script navigates to the profile, dumps the rendered DOM, and emits the canonical envelope in one step:

```bash
browser-serialiser instagram.com/auth-ig-profile HANDLE
```

The output is the canonical envelope `{result, cursor, hasMore, fault}`. A profile is a single read, so `cursor` is null and `hasMore` is false. On success `fault` is null and `result` is the superset object — the server validates its required subset against `social/api/contracts/ig-profile.schema.json` and discards the rest, while a skill caller reads whichever fields it wants:

- `username`, `full_name`, `pk`
- `is_private` (boolean)
- `follower_count`, `following_count`, `media_count` — integers, or null when the page did not render them
- `category_name`, `biography`, `external_url`
- the extras `url`, `followers_raw`, `following_raw`, `posts_raw` (the rounded count strings as the header shows them, e.g. `27K`), `avatar`, `caption_snippet`, `og_description`, `meta_description`, `html_size`, `is_verified`, `business_category_name`

Instagram has no separate "about" page on the web; the counts, display name, avatar and recent-caption snippet come from the server-rendered `<meta>` tags (`og:title`, `og:image`, `og:description`, `meta name=description`), parsed positionally so they stay locale-agnostic. The exact follower count comes from the rendered header's `title=` attribute when present. `is_verified`, `business_category_name`, `biography` and `external_url` are pulled from inline-hydrated JSON when the page carries it — typically the viewer's own profile or one the viewer follows closely — and are null otherwise.

A removed or non-existent profile sets `result` to null and `fault` to `{shape:"removed", detail}`; a login wall (session expired or never logged in) sets `result` to null and `fault` to `{shape:"login_wall", detail}`.

## 5. DM inbox metadata (noninvasive)

This script reads inbox metadata only. It must not be modified to read individual thread content. If you need message content from a specific thread, that is a separate, invasive operation. Write a different script with a different name.

```bash
browser-serialiser instagram.com/auth-inbox-noninvasive list
```

Emits JSON with one entry per thread: `username`, `full_name`, `thread_id`, `last_activity_iso`, `last_snippet` (up to 120 chars of the last message text or a type label), `unseen` (boolean), `is_group`.

Requires a logged-in session. Does not navigate to `/direct/inbox/` to avoid triggering a "user is viewing inbox" presence beacon. The script declares the seen-mutation URL patterns (`*/seen/*`, `*/mark_seen*`, `*item_seen*`, `*direct_thread*`) via the harness `veto` verb before the first navigation; the harness refuses any matching request so it cannot leave the browser. The read-state guarantee is structural — there is no runtime double-read needed.

## 6. Recent posts for a handle

```bash
browser-serialiser instagram.com/auth-fetch-recent-posts posts HANDLE
browser-serialiser instagram.com/auth-fetch-recent-posts posts HANDLE --limit 50
```

Default limit is 12. The posts come from the profile page's own GraphQL timeline query, twelve to a page: the script captures the profile and, when `--limit` exceeds 12, scrolls for further pages until the limit is reached or the timeline reports no next page. The REST feed `/api/v1/feed/user/<user_id>/` answers Instagram's HTML 404 page (observed 2026-10-29).

`post_count: 0` means the account has no posts. A private account the session cannot see into returns `is_private: true` with a `note`; a public profile page that loaded no timeline is a fault, not an empty result.

(`--raw-out PATH`, which writes the unparsed feed items to a file, is a direct-tclsh-only option; the serialiser path's safe interpreter has no file access, so the parsed JSON on stdout is the only output there.)

Each post entry includes:

- `post_id`, `shortcode`, `url`, `post_type` (image/video/carousel/reel), `taken_at_iso`
- `like_count`, `comment_count`, `play_count`, `ig_play_count`, `fb_play_count`, `view_count`, `media_repost_count`, `fb_like_count`, `fb_comment_count` (play/view/reshare null on stills; the `fb_*` are null unless the post was cross-posted to Facebook)
- `video_duration` (seconds, null on stills), `like_and_view_counts_disabled` (the creator hid metrics)
- `caption`, `hashtags` (regex-extracted from caption), `mentions` (regex-extracted from caption)
- `tagged_users` (the "tag people" feature on the post; aggregated across carousel slides)
- `coauthors` (the dual-author collab-post feature)
- `sponsors` (branded-content sponsor tags)
- `is_paid_partnership`, `location`

The five handle-bearing fields above (`mentions`, `tagged_users`, `coauthors`, `sponsors`, plus paid-partnership context) are what the collab-expansion script in §7 walks to find candidates.

## 7. Collab partner expansion (multi-handle spider)

```bash
browser-serialiser instagram.com/auth-collab-expand expand handle1,handle2,handle3
browser-serialiser instagram.com/auth-collab-expand expand handle1,handle2 --posts-per-handle 36
```

Walks a list of input handles, fetches recent posts for each (paginated via §6's helpers), and accumulates the union of `tagged_users`, `coauthors`, `sponsors`, and caption `mentions` across all posts. (The legacy `--from <file>` seed-list option is direct-tclsh-only; pass the CSV positional under the serialiser.) Outputs candidate handles NOT already in the input set, ranked by explicit-collab signal first (tagged + coauthor + sponsor counts) and then by caption-mention count and breadth of source handles.

Each candidate row carries the four per-signal counts, a `total`, and a sorted `sources` list of input handles whose posts surfaced the candidate. `skipped` lists each input handle whose posts were not read (unresolvable, private, or no timeline loaded) with its `reason`. Multi-source candidates (handles surfaced by several different input accounts) rank higher than single-source ones at equal signal strength.

This is single-level expansion. For "spider" behaviour (recursively expanding), feed the top N candidates as input to a second run.

Default `--posts-per-handle` is 24 (about two pages). Pacing: roughly one feed page every 2 seconds, plus a 2-second gap between input handles. A run over 5 input handles at 24 posts each takes about a minute.

## 8. Post comments (for comment-circle discovery)

```bash
browser-serialiser instagram.com/auth-fetch-post-comments comments SHORTCODE
browser-serialiser instagram.com/auth-fetch-post-comments comments POST_ID
```

Accepts a shortcode (e.g. `DXsPrn5AvNH`), a full post_id from the feed API (`<media_id>_<user_id>`), or a bare numeric `media_id`. Shortcode-to-media-id conversion is a local base64 decode, so no extra fetch is needed to resolve. Navigates to the post permalink (the covering view), then reads `/api/v1/media/<media_id>/comments/` via the policed `api` verb.

From overseers-desk/magazines, MIT.

More from overseers-desk/magazines

Signals

Stars
1
Forks
0
Open issues
36
Last commit (this folder)
Sep 5, 2026 (1 month ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from overseers-desk

Cite this page

instagram skill. Agent Mart. https://agentmart.dev/skills/overseers-desk-instagram (last updated 2026-10-24)