<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sarah Mitchell</title>
    <description>The latest articles on DEV Community by Sarah Mitchell (@sarah_mitchell_ig).</description>
    <link>https://dev.to/sarah_mitchell_ig</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4243716%2Fc582a74d-71fc-4f21-b81a-806ea06722d7.jpeg</url>
      <title>DEV Community: Sarah Mitchell</title>
      <link>https://dev.to/sarah_mitchell_ig</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sarah_mitchell_ig"/>
    <language>en</language>
    <item>
      <title>How Instagram's September 2026 Change Broke Follow Trackers (and How Snapshot Diffing Works)</title>
      <dc:creator>Sarah Mitchell</dc:creator>
      <pubDate>Sat, 14 Nov 2026 00:43:34 +0000</pubDate>
      <link>https://dev.to/sarah_mitchell_ig/how-instagrams-september-2026-change-broke-follow-trackers-and-how-snapshot-diffing-works-2bl2</link>
      <guid>https://dev.to/sarah_mitchell_ig/how-instagrams-september-2026-change-broke-follow-trackers-and-how-snapshot-diffing-works-2bl2</guid>
      <description>&lt;p&gt;For years, every "recent follows" tracker on the internet was built on one quiet assumption: &lt;strong&gt;Instagram returns a Following list newest first.&lt;/strong&gt; If you wanted to know who someone followed last, you fetched their list and read the top.&lt;/p&gt;

&lt;p&gt;On 9 September 2026, that assumption broke. There was no announcement and no changelog. A whole category of tools just started showing wrong results on the same morning.&lt;/p&gt;

&lt;p&gt;This post explains what changed, why the "read the top of the list" model failed, and how the fallback most tools moved to, &lt;strong&gt;snapshot diffing&lt;/strong&gt;, actually works. There's code, and a list of the bugs you will hit if you build it yourself.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclosure: I work on &lt;a href="https://klupt.io/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=snapshot_diff_article" rel="noopener noreferrer"&gt;Klupt&lt;/a&gt;, one of the trackers that broke that day. I'll say where it fits at the end. This post was written with AI tools.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The old model: order was the only clock
&lt;/h2&gt;

&lt;p&gt;Instagram never shared &lt;em&gt;when&lt;/em&gt; someone followed an account. There is no &lt;code&gt;followed_at&lt;/code&gt; field on another person's Following list. The only signal was position: the newest follows sat at the top.&lt;/p&gt;

&lt;p&gt;So most trackers were very thin. Simplified, they did this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The pre-September model: trust the server's order.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;following&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchFollowingList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// newest first (assumed)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;recentFollows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;following&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No storage, no history. The tool didn't sort anything. It just passed Instagram's order along to the user. That made these tools cheap to run and instant on the first search, which is exactly what people wanted.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed on 9 September 2026
&lt;/h2&gt;

&lt;p&gt;The list started coming back &lt;strong&gt;ranked instead of chronological&lt;/strong&gt;. Gramlens, a follower export tool, &lt;a href="https://gramlens.com/blog/instagram-followers-not-in-chronological-order" rel="noopener noreferrer"&gt;describes the new order&lt;/a&gt; as ranked for the viewer, so two people can open the same profile and see two different orders. IG Detective &lt;a href="https://www.igdetective.com/guides/instagram-follow-tracking-september-2026-update" rel="noopener noreferrer"&gt;paused follow tracking&lt;/a&gt; because some "new" follows it showed were not new at all.&lt;/p&gt;

&lt;p&gt;For the thin model above, this is the worst possible failure. Nothing errors. The code still returns 20 accounts. They are just the wrong 20, and the UI still labels them "recent".&lt;/p&gt;

&lt;p&gt;That's a good lesson in general: &lt;strong&gt;if your feature depends on an undocumented ordering, you have no contract, only a habit.&lt;/strong&gt; It can change on any day without a single failed request.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fallback: snapshot diffing
&lt;/h2&gt;

&lt;p&gt;If the server won't tell you what is new, you can work it out yourself: save the full list now, fetch it again later, and compare. Anything in the new list that wasn't in the old one is a new follow.&lt;/p&gt;

&lt;p&gt;The core is a set difference:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Compare two snapshots of a Following list.
 * Each item: { id: string, username: string }
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;diffSnapshots&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;prevIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;currIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;added&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;prevIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;removed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;currIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a polling loop around it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchFullFollowingList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;previous&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLatestSnapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;saveSnapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;added&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baseline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// first run&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;added&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;diffSnapshots&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;added&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;since&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;takenAt&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's maybe 30 lines. The real work is in the edge cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Six bugs you will hit
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Keying on usernames
&lt;/h3&gt;

&lt;p&gt;Usernames change. If you diff on &lt;code&gt;username&lt;/code&gt;, every rename looks like one unfollow plus one new follow. Always diff on the stable account ID and treat the username as display data.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The baseline problem
&lt;/h3&gt;

&lt;p&gt;The first run has nothing to compare against, so it returns zero new follows. Your user searched a profile because they wanted an answer &lt;em&gt;now&lt;/em&gt;, and you show them an empty list. This is the biggest product problem with snapshots, and code can't fix it. You can only be honest in the UI: "We started watching today. New follows will appear from here."&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Partial fetches create fake unfollows
&lt;/h3&gt;

&lt;p&gt;Big lists are paginated. If page 7 of 12 fails or gets rate limited, your "current" snapshot is missing hundreds of accounts. Diff that against a full snapshot and you report hundreds of unfollows that never happened.&lt;/p&gt;

&lt;p&gt;Rule: &lt;strong&gt;never diff an incomplete snapshot.&lt;/strong&gt; Compare the number of items you fetched with the profile's following count, and throw the snapshot away if they are too far apart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isComplete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expectedCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tolerance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.02&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expectedCount&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;expectedCount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;expectedCount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;tolerance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The small tolerance is there because counts and lists are not always updated at exactly the same moment.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Flapping from caches
&lt;/h3&gt;

&lt;p&gt;Sometimes an account disappears from one fetch and comes back in the next, because of caching or eventual consistency on the server side. If you alert on the first sighting, users get "new follow" pings for accounts that were always there.&lt;/p&gt;

&lt;p&gt;A simple fix is to confirm a change across two checks before you tell anyone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Only report an account once it has appeared in two snapshots in a row.&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;confirmedAdds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addedNow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;addedLastRun&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addedLastRun&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;addedNow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It costs you one poll interval of delay. In return, you send far fewer false alerts.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Lists that go private or hidden
&lt;/h3&gt;

&lt;p&gt;A profile can switch to private, or the list can stop being available. A fetch that returns nothing is not the same as "they unfollowed everyone". Handle "can't read" as its own state, and don't run a diff on it.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Your timestamps are only as good as your poll interval
&lt;/h3&gt;

&lt;p&gt;With snapshots, the only date you can attach to a follow is "somewhere between my last check and this one". Poll every hour and your resolution is one hour. Poll once a day and it's one day. Any tool that shows an exact time for an &lt;em&gt;old&lt;/em&gt; follow is guessing, because Instagram doesn't share that data for other people's lists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Snapshot diffing vs real order
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Read the order&lt;/th&gt;
&lt;th&gt;Snapshot diffing&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Works on first search&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No, needs a baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Finds follows from before you started&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Survives an ordering change&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage needed&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Full list per check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exact dates&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Only "between check A and B"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Snapshots are honest and robust. They are great for watching your &lt;strong&gt;own&lt;/strong&gt; followers over months. They just can't answer the question most people actually type into Google: "who did this person follow recently?" A tool that starts counting today can't answer that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Klupt fits
&lt;/h2&gt;

&lt;p&gt;Klupt broke on 9 September like everyone else, and for a few weeks it also ran on snapshots. Since late October 2026 it shows a public profile's recent follows in real order again, newest first, from the first search. I won't go into how we read the list, but the hourly snapshot diff is still there on top of it: it powers the NEW badges and the Telegram alerts when a tracked profile follows someone.&lt;/p&gt;

&lt;p&gt;If you want to see the result, the &lt;a href="https://klupt.io/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=snapshot_diff_article" rel="noopener noreferrer"&gt;web tracker&lt;/a&gt; needs no login, and the &lt;a href="https://klupt.io/iphone-app?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=snapshot_diff_article" rel="noopener noreferrer"&gt;iPhone app&lt;/a&gt; can also check private accounts you already follow, with the login kept on your device. A quick way to test any tracker, ours included: follow a new account from a second account, search that second account, and see if the follow shows up at the top.&lt;/p&gt;

&lt;p&gt;Two rules we keep, and that I'd suggest to anyone building in this space:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Public data only.&lt;/strong&gt; If a tool asks for someone's Instagram password to "see" their list, walk away.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't fake precision.&lt;/strong&gt; Show order or "seen between A and B". Never invent dates.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Have you shipped something that depended on an undocumented API ordering and then broke? I'd love to hear how you found out, and what you replaced it with.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>privacy</category>
      <category>instagram</category>
    </item>
  </channel>
</rss>
