Inspiration
Sometimes I and my friends download content from Instagram, from each other. But there is no way to do it reliably. Public tools and websites are designed simply to download public media. Right clicking and saving media doesn't work everywhere on Instagram and nor does it give you the highest quality. Tools like instaloader exist but are not targeted towards non-tech people. Plus they also lack some quality-of-life features.
What it does
If you log into Instagram, your browser whenever sends request to Instagram, those are authenticated. Thus, a browser extension can utilize that authenticated session without having to extra steps of extracting the cookies. It also makes it very user-friendly. Doing so we are able to download all sorts of media from Instagram, and media in private accounts you have allowed you into their follower list.
How we built it
GramGrab is a Manifest V3 browser extension built with React and TypeScript. It produces separate Chromium and Firefox builds from the same source code. The React interface communicates with a background worker responsible for fetching Instagram metadata, decoding responses, preparing previews, managing downloads, and coordinating the workspace and download history. Instagram’s internal APIs are undocumented and can change without warning, so every response is decoded through strict Effect Schemas. Real, sanitized Instagram responses are kept as fixtures and exercised by automated tests. If Instagram changes an important part of its response format, GramGrab fails loudly with a useful error instead of silently returning incorrect data. I bootstrapped the project with Codex and continued using it as a development partner for implementation, testing, architecture, and documentation.
Challenges we ran into
It was necessary that the Instagram response shape is known and tested against, thus I needed fixtures. I asked codex to generate a script I can run in devtools to download the fixtures. It took a few attemps and then it worked. But fixtures contains sensitive information too, and thus a sanitizer script was also necessary. LLMs aren't very good at writing Effect code yet, so putting a vendored repo to let the LLM use the actual source code to figure our Effect was a good idea. Cross-browser support introduced another challenge. Chromium and Firefox implement parts of Manifest V3 differently, especially their background worker configuration and extension APIs. GramGrab therefore generates browser-specific manifests while sharing the rest of its code.
Accomplishments that we're proud of
I am proud that GramGrab grew beyond a basic “paste a URL and download” utility. It now supports a broad range of Instagram media, selective batch downloads, previews, video-frame exports, silent-video exports, local history, and a dedicated workspace for larger collections. The part I am most proud of is the reliability work behind the interface. Instagram responses are handled with strict Schemas, typed failures, real sanitized fixtures, and focused tests. When Instagram changes, the extension is designed to explain what happened rather than quietly breaking or producing misleading results. I am also proud that this remains a local-first tool. It does not require users to send their Instagram cookies or media URLs to a third-party downloader, and it does not depend on an application backend or analytics service. Finally, supporting both Chromium and Firefox from one maintainable codebase was an important milestone.
What we learned
I learned that building a downloader is less about triggering a browser download and more about reliably discovering the correct media, handling authentication, adapting to unstable APIs, and presenting failures honestly. I also learned that realistic fixtures are essential when integrating with an undocumented service. Handwritten test data can verify edge cases, but it rarely captures all the details and irregularities of a real production response. Privacy must be designed into development tooling as well as the final product. A local-first extension can still leak sensitive information through fixtures, logs, or diagnostics if those paths are not treated carefully. Finally, I learned that AI coding tools work best when they are given strong context and reliable source material. Vendoring Effect’s source code and defining clear project conventions made Codex substantially more effective than relying on generated guesses.
What's next for GramGrab
The next step is to make GramGrab easier to install and use by preparing polished releases for browser extension stores. I also want to continue improving its resilience to Instagram changes. This includes making protocol updates and fixture refreshes easier, expanding diagnostics without exposing private data, and keeping recovery messages useful when an endpoint changes or a request is rate-limited. On the product side, I would like to refine the workspace experience, improve accessibility and keyboard navigation, and explore more download organization options while keeping the extension focused, private, and simple.
Built With
- effect
- mv3
- react
- typescript
Log in or sign up for Devpost to join the conversation.