topfoc.usStart a buildMark OS Social
A Manifest V3 Chrome extension for the MarkOS content platform. It pulls Instagram posts and reels, with their media, captions and engagement numbers, into the platform's library from the tab the user is already sitting in.
- Chrome extension
- TypeScript
- MV3
- Automation

- Client
- MarkOS
- Role
- Full extension build
- Year
- 2025
- Stack
- TypeScript · Chrome MV3 · Webpack
The challenge
The content team was collecting reference reels by hand. Open Instagram, find the post, save the video, screenshot it, copy the caption, write down the view count, upload the lot into MarkOS and tag it to the right brand. Ten minutes a post, and the numbers were usually typed in wrong.
An external scraper was the obvious build and the wrong one. It wants credentials, it wants a proxy pool, and it stops working the week Instagram decides it dislikes the traffic. Meanwhile the person doing this job is already logged in, in a browser, looking at the exact post they want.
The approach
So the tool lives in the browser they were using anyway. The extension puts an extract button on feed posts, reel tiles and profile grids, and media requests go through Instagram's own internal API using the session cookies that are already in the tab. No login flow, no proxies, no second copy of somebody else's auth problem.
Instagram re-renders its DOM constantly, so button injection runs off a MutationObserver. A single pass at load would only ever catch the first screen. An extraction tracker marks what has already been pulled and draws an overlay on the tile, which is what stops the same reel going up three times.
Batch mode is the feature that actually changed the job. One button under the profile header walks the grid, scrolls each tile into view, fires its extract and waits for that to finish before moving on, with a limit field for when you want the top twenty rather than the last four hundred.
Screenshots get cropped to the tile's bounding box. MV3 service workers have no DOM and therefore no canvas, so the crop happens in an offscreen document: the worker captures the visible tab, hands the data URL and the rectangle over, and gets a tight image back. Everything posts to the MarkOS content-items endpoint with a brand id attached, and a test-mode toggle aims the same pipeline at a local Express server so development never touches production content.
The outcome
Collecting a reel became a click, and collecting a profile's worth became one button and a wait. Captions, view counts, like counts and thumbnails arrive as structured records filed under the right brand instead of being retyped by somebody at the end of a long afternoon.
The fragile part is written down in the README so nobody has to discover it the hard way: this rides on Instagram's DOM and its internal API, and both of those move. The selectors sit in one constants file, so when it breaks it breaks somewhere you can find.
What came of it
- 1Extract button injected into feed posts, reel tiles and profile grids
- 2Batch capture across a whole profile grid, with a limit field and per-item progress
- 3Tile-cropped screenshots taken in an MV3 offscreen document
- 4Media, caption, username, likes, comments and view count posted as a single record

Mark OS Social