Reverse Engineering Instagram
DEV Community

Reverse Engineering Instagram

The string in an Instagram post URL is a database key. Most of what's known about Instagram's internals is documented somewhere, but it's scattered across engineering posts, one-off repos and OSINT write-ups. This pulls the best of it into one place, with the parts people usually skip.

One boundary first. Meta's terms prohibit unauthorized use of private endpoints, and the repo I cite below says as much about itself. This piece covers how the system is built, not how to drive it without permission.

The Shortcode Is the Primary Key

Instagram's sharding post describes several thousand logical shards mapped in code to far fewer physical shards, where each logical shard is a Postgres schema. IDs are generated inside Postgres with PL/pgSQL, per the original write-up.

The layout, according to one summary of Mike Krieger's SFPUG slides, is the top 41 bits as milliseconds since a custom epoch of 1314220021721, then a 13-bit shard ID and a 10-bit sequence. The slides are linked there as the SFPUG deck.

The shortcode in /p/ and /reel/ URLs is that ID in base 64. The alphabet is A-Z a-z 0-9 - _, with A as 0 and underscore as 63. One caveat from the same decoder write-up: Instagram has never published the shortcode mapping, so it is community-documented.

I ran it to check. This works with arithmetic alone:

A = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
EPOCH = 1314220021721
def decode(shortcode):
    n = 0
    for c in shortcode:
        n = n * 64 + A.index(c)
    return {"id": n, "ms": (n >> 23) + EPOCH, "shard": (n >> 10) & 0x1FFF, "seq": n & 0x3FF}

CWvxAY7B0ci decodes to ID 2715604631366879010, created 2021-11-26 16:48:40.527 UTC, shard 465, sequence 802. CSZUyULIgWQ decodes to 2021-08-10 13:33:13.071 UTC, shard 2177. The custom epoch itself comes out as 2011-08-24 21:07:01 UTC.

Because the timestamp leads, posts sort chronologically by ID, and the shard bits tell you which logical shard holds the row. The 10-bit sequence caps one shard at 1,024 IDs per millisecond.

The same trick works outside Instagram. Ryan Benson reverse-engineered the fbclid parameter Meta appends to outbound links. Per the decoder summary, a modern value contains a clck field holding click time in seconds, calibrated against Unix time with an offset of 1,704,140,976, while most other fields are untested. The author is explicit that this is independent research and Meta documents none of it.

Explore Is a Distillation Chain, Not a Model

Two Meta engineering posts describe Explore, five years apart. They describe different eras of the same system, so don't merge their numbers. The 2019 post opens with scale: a ranking funnel that extracts 65 billion features and makes 90 million model predictions every second.

The mechanics are the interesting part:

  • IGQL. Candidate sources are written in a domain-specific language with a Python-like syntax that executes in optimized C++. Sources become subqueries, and a combiner rule blends them by weight.
  • ig2vec. It applies word2vec to account IDs, treating the accounts a person interacts with in a session as a sentence. The embedding is account-level rather than media-level because interest communities like vintage tractors are hard to catalog by content. Lookups run on FAISS.
  • The funnel. 500 sampled candidates go to a distillation model that picks 150, then a lightweight network picks 50, then a deep network picks 25 for the first page.

The distillation stage is a cost trick. The cheap first-pass model is trained to replicate the heavier models' outputs, optimizing NDCG loss, so more candidates can be scored per request.

The 2023 post restructures this into four stages (retrieval, first-stage ranking, second-stage ranking, final reranking) and adds three details that rarely get discussed:

  • Cacheability constrains the features. Two Tower models can cache user and item embeddings, but they can't consume user-item interaction features, which are usually the most powerful, without losing that cacheability.
  • The first stage predicts the second stage. The label is whether a media item lands in the top K of the second-stage ranking. That's distillation again, with the heavy model's output as the target.
  • Heavy models are partly precomputed. Because the multi-task, multi-label model is expensive at peak hours, recommendations for some users are precomputed off-peak.

The final score is a hand-set weighted sum. In the 2023 post's formulation, predicted click and like probabilities are added and the predicted "see less" probability is subtracted, each with its own weight. The 2019 version also applies a diversity penalty that grows as the same author or seed account recurs further down the ranked batch.

Weights are tuned two ways. Online Bayesian optimization can take more than a month to converge, while offline tuning needs only hours but depends on offline metrics correlating with online ones. Both posts also mention models retrained on fresh data, with hourly fine-tuning in the 2023 one.

The Client Is Mostly a Rendering Engine

On the web, Threads reverse-engineering notes report that the client uses Meta's Relay GraphQL client against a backend that appears to disallow arbitrary queries. That's the persisted-query pattern. As Crawlee's write-up explains in general terms, persisted queries replace the full query text with a precomputed hash. The practical consequence: Meta rotates the doc_id periodically, so anything built on hardcoded IDs breaks on schedule.

On mobile, a lot of UI is Bloks. TechCrunch's coverage of Instagram Lite describes it as a framework where logic is defined once server-side and rendered as a native app. The Threads notes add that the mobile apps use Bloks for authentication. For reverse engineers this means a login screen is server-sent data, not compiled UI.

The most detailed public teardown I found is Brainrot3d, built from static analysis of the decrypted arm64 binary of Instagram iOS 435.0.0, with no instrumented device and no network interception. The README documents several things worth knowing as architecture:

  • Rotating password-encryption keys. The public key isn't baked into the app. The server delivers it live from a pre-auth sync call, and it rotates.
  • Device identity as a risk signal. The README says a set of GUIDs is derived deterministically so a session resumes as the same "device", which keeps Instagram's new-device risk checks happy.
  • No body HMAC in that build. The legacy signing prefix survives only as a literal string, with integrity carried by the bearer token, claim header, machine ID and device GUIDs.
  • A streaming Reels feed. The Reels discovery response is a stream of concatenated top-level JSON objects, not one document.
  • Ranking metadata ships to the client. Each reel carries a decodable tracking token containing the media PK, viewer ID and serve time, plus ranked_at and feed-position fields. A separate seen-state endpoint reports watch time and completion.

Treat the repo's claims as one researcher's findings for one app version. The author says the same: the endpoints can change at any time, and use may violate Instagram's terms. Note also that the app ships with certificate pinning, which the author calls irrelevant to a reimplemented client.

The Python Stack Underneath

Instagram's static analysis post states that the server is entirely Python powered, with some Cython and C++ extensions, and uses Pyre for whole-program type checking.

The tooling that fell out is open source. LibCST builds a lossless concrete syntax tree for codemods and linters. Cinder is the runtime side: a method-at-a-time JIT with a function inliner, plus inline caching, Static Python and Strict Modules. The JIT's own description notes type information and specialization happen only within a function.

What Reverse Engineering Can't Tell You

Everything above shows structure, and none of it shows weights. The value-model coefficients, the feature lists and the current production funnel are not public, and both ranking posts are years old. Third-party "Instagram algorithm" explainers often present these architectures as current fact with invented numbers attached. The clean way to separate signal from folklore is to check whether a claim traces to a Meta engineering post or a binary teardown.

Follow for more coverage on MCP, agentic AI, and AI infrastructure.

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.