<?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: Miles Hilliard</title>
    <description>The latest articles on DEV Community by Miles Hilliard (@mhilliard27).</description>
    <link>https://dev.to/mhilliard27</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3935398%2Fcb2d2a27-5502-49ce-8c8f-56f48457498a.jpg</url>
      <title>DEV Community: Miles Hilliard</title>
      <link>https://dev.to/mhilliard27</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mhilliard27"/>
    <language>en</language>
    <item>
      <title>countapi.xyz is dead. Here's the drop-in replacement I found (and actually use)</title>
      <dc:creator>Miles Hilliard</dc:creator>
      <pubDate>Sat, 16 May 2026 19:37:27 +0000</pubDate>
      <link>https://dev.to/mhilliard27/countapixyz-is-dead-heres-the-drop-in-replacement-i-found-and-actually-use-16b8</link>
      <guid>https://dev.to/mhilliard27/countapixyz-is-dead-heres-the-drop-in-replacement-i-found-and-actually-use-16b8</guid>
      <description>&lt;p&gt;If you've been using countapi.xyz for page view tracking, button click counters, or really anything that just needed a simple number that goes up... you've probably noticed it's gone. No announcement, no migration guide, just a dead URL.&lt;/p&gt;

&lt;p&gt;And honestly, it was one of those APIs that was so useful precisely because it asked nothing of you. No account. No API key. No SDK to install. Just fetch a URL and get a number back. It was perfect.&lt;/p&gt;

&lt;p&gt;So when it died, a lot of people were left hunting for alternatives. Most of what I found either required signing up, had weird rate limits buried in the fine print, or was just overkill for what is fundamentally a very simple problem.&lt;/p&gt;

&lt;p&gt;Then I found &lt;a href="https://countapi.mileshilliard.com" rel="noopener noreferrer"&gt;countapi.mileshilliard.com&lt;/a&gt; and it's basically exactly what we lost.&lt;/p&gt;




&lt;h2&gt;
  
  
  What it is
&lt;/h2&gt;

&lt;p&gt;It's a free, open source counting API built as a direct spiritual successor to countapi.xyz. No signup. No API keys. No headers. You just hit an endpoint and it gives you a number.&lt;/p&gt;

&lt;p&gt;The whole thing runs on a Python serverless backend with Redis, and it's hosted on OCI with near 99% uptime (there's a public UptimeRobot dashboard you can check yourself).&lt;/p&gt;

&lt;p&gt;The concept is dead simple: every counter is identified by a unique &lt;strong&gt;key&lt;/strong&gt;. That's it. You pick a key name, and the API tracks a number against it. Since there are no namespaces like the original had, you just want to make your key specific enough that nobody else is going to accidentally share it, something like &lt;code&gt;johns-blog-homepage-visits&lt;/code&gt; rather than just &lt;code&gt;visits&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The endpoints
&lt;/h2&gt;

&lt;p&gt;There are really only three you'll ever use:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hit (increment by +1)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /api/v1/hit/your_key
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Key updated successfully"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"42"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Get (read without incrementing)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /api/v1/get/your_key
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Key requested successfully"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"42"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Set (jump to a specific value)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /api/v1/set/your_key?value=100
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Key set successfully"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"old_value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"42"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"100"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the whole API. There's also &lt;code&gt;/api/v1/status&lt;/code&gt; and &lt;code&gt;/health&lt;/code&gt; if you want to ping it for monitoring purposes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Using it in practice
&lt;/h2&gt;

&lt;p&gt;Adding a page view counter to any site is maybe 5 lines of JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This page has been visited &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"visits"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; times.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://countapi.mileshilliard.com/api/v1/hit/my-site-homepage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visits&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're on a platform that doesn't allow JavaScript at all (like certain Notion pages or some README renderers), there's even a tracking pixel approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://countapi.mileshilliard.com/api/v1/hit/my-site-visits"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"display:none;"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No JS required. The hit happens server-side when the image loads.&lt;/p&gt;




&lt;h2&gt;
  
  
  Migrating from countapi.xyz
&lt;/h2&gt;

&lt;p&gt;If you were using countapi.xyz, your old calls probably looked like 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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.countapi.xyz/hit/mysite.com/visits&lt;/span&gt;&lt;span class="dl"&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 new equivalent is:&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://countapi.mileshilliard.com/api/v1/hit/mysite-visits&lt;/span&gt;&lt;span class="dl"&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 main difference is there are no namespaces anymore, so you fold your old namespace and key together into one unique key. Everything else works the same way.&lt;/p&gt;




&lt;h2&gt;
  
  
  A few things worth knowing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;All keys are public.&lt;/strong&gt; Anyone who knows your key name can read or hit your counter. This is by design and is the tradeoff for having zero auth overhead. Just don't use it to store anything sensitive (not that a number really could be, but still).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keys don't expire.&lt;/strong&gt; If you want to "reset" a counter, use the &lt;code&gt;/set&lt;/code&gt; endpoint or just start using a new key name.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There is rate limiting&lt;/strong&gt;, though the docs describe it as "extremely generous." Someone apparently stress tested it without warning, which is how rate limiting got added in the first place. The docs have a great line about this: "Shoot me an email before you try to... if you wouldn't mind."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's open source.&lt;/strong&gt; The whole thing is on GitHub at &lt;a href="https://github.com/syntaxerror019/countapi" rel="noopener noreferrer"&gt;syntaxerror019/countapi&lt;/a&gt; if you want to self-host or contribute.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I like it
&lt;/h2&gt;

&lt;p&gt;There are absolutely fancier analytics tools out there. But sometimes you really do just want a number that goes up. This API gets that. It doesn't ask you to create an account to track 12 page views on your personal blog. It doesn't require you to read 40 pages of docs. It just works.&lt;/p&gt;

&lt;p&gt;The fact that it's a community project filling a gap that a commercial service left behind makes it even better. If you end up using it, maybe give the repo a star or drop the maintainer a note. Small projects like this run on that kind of encouragement.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Site: &lt;a href="https://countapi.mileshilliard.com" rel="noopener noreferrer"&gt;countapi.mileshilliard.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/syntaxerror019/countapi" rel="noopener noreferrer"&gt;github.com/syntaxerror019/countapi&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Uptime dashboard: linked from the site nav&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
