TLDR - I finished a small project that I am sharing for my friends on DEV, that allows you to put your followers count on your Github!
I had started this nonsense last year, and like many silly side projects, let it go to the wayside. But there was one consistent tiny reminder in my email everyday: "Run failed for Github Actions..." 😂
I said well, I could just delete it all. But that bothered me. I should be able to get it to work, right? Feeling determined today, I said enough is enough with the annoying emails and I am going to fix this. A little tweak to the api calling and a little deletion of unused code that I had commented out and things began to get much more clear.
I'm going to share the full code of my working github actions file that is working for me, so someone else on here that wants it doesn't have to silently succumb to a year of annoying emails like I did. Evidence of that can be seen with successful run #343 - the first successful run.
Here's the good part you have been looking for.
YAML File:
name: Update DEV.to Followers Count
on:
schedule:
# Runs at midnight UTC daily
- cron: '0 0 * * *'
workflow_dispatch:
permissions:
contents: write
jobs:
update-count:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Run the update script
env:
DEVTO_API_KEY: ${{ secrets.DEVTO_API_KEY }}
DEVTO_USERNAME: annavi11arrea1
run: node update_script.js
- name: Commit updated README
run: |
if git diff --quiet -- README.md; then
echo "Follower count has not changed."
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add README.md
git commit -m "Update DEV.to follower count"
git push
Notes:
Please remember to use environment variables in your code for API keys, don't hard code them into this! We want to keep our privilege to use DEV API for free. 🦋
You will need to specify where in your README.md to place the output. You will need appropriate tags. I did it like this:
Scroll so you see the whole thing, there is a start and end tag.
<!-- DEVTO-FOLLOWERS-COUNT:START -->**34996** DEV.to followers<!-- DEVTO-FOLLOWERS-COUNT:END -->
I'm so psyched I got this working. I'm not here to brag about my followers, but we might all want to brag silently on our own profiles elsewhere. Haha.
Important changes made: make sure that I gave it write permissions, and also that the write is auto-pushed when the job runs. Key factors for a real update. Hmm, I wonder how else I might use Github actions for auto-updates?
Shout out to @fm for calling me out. Here is my update_script.js 😂
const fs = require("fs");
const https = require("https");
const DEVTO_API_KEY = process.env.DEVTO_API_KEY;
const DEVTO_USERNAME = process.env.DEVTO_USERNAME || "annavi11arrea1";
const README_FILE = "README.md";
const START_MARKER = "<!-- DEVTO-FOLLOWERS-COUNT:START -->";
const END_MARKER = "<!-- DEVTO-FOLLOWERS-COUNT:END -->";
const USER_AGENT = "AnnaVi11arrea1-GitHub-Actions";
if (!DEVTO_API_KEY) {
throw new Error("Missing required DEVTO_API_KEY environment variable.");
}
const parseResponsePreview = (data) => {
const trimmed = data.trim();
return trimmed ? trimmed.slice(0, 500) : "<empty>";
};
const fetchJson = (path) => {
const options = {
hostname: "dev.to",
port: 443,
path,
method: "GET",
headers: {
"api-key": DEVTO_API_KEY,
Accept: "application/vnd.forem.api-v1+json",
"User-Agent": USER_AGENT,
},
timeout: 15000,
};
return new Promise((resolve, reject) => {
const req = https.request(options, (res) => {
let data = "";
res.on("data", (chunk) => {
data += chunk;
});
res.on("end", () => {
if (res.statusCode !== 200) {
const preview = parseResponsePreview(data);
reject(
new Error(
`DEV.to API request failed (${res.statusCode} ${res.statusMessage || "Unknown"}). Response preview: ${preview}`
)
);
return;
}
try {
resolve(JSON.parse(data));
} catch (error) {
reject(new Error(`Failed to parse API response. Response data: ${data}`));
}
});
});
req.on("timeout", () => req.destroy(new Error("DEV.to API request timed out.")));
req.on("error", reject);
req.end();
});
};
const getFollowersCount = async () => {
const perPage = 1000;
let page = 1;
let totalCount = 0;
while (true) {
const followers = await fetchJson(
`/api/followers/users?page=${page}&per_page=${perPage}`
);
if (!Array.isArray(followers)) {
throw new Error("DEV.to followers endpoint returned an invalid response.");
}
totalCount += followers.length;
if (followers.length < perPage) {
return totalCount;
}
page += 1;
}
};
const updateReadme = async () => {
const count = await getFollowersCount();
let readmeContent = fs.readFileSync(README_FILE, "utf8");
const newContent = `${START_MARKER}**${count}** DEV.to followers${END_MARKER}`;
const regex = new RegExp(`${START_MARKER}[\\s\\S]*?${END_MARKER}`, "g");
readmeContent = readmeContent.replace(regex, newContent);
fs.writeFileSync(README_FILE, readmeContent);
console.log("README updated with new follower count:", count);
};
updateReadme().catch((error) => {
console.error(error);
process.exit(1);
});

Top comments (94)
ooo very nice.
I know right. 😜 but whats cool is now that I have a github action confidently working, I feel well suited to try other sorts of workflows with github actions. I think thats the real win here! Thanks Francis! ✨️
Yeah, cool alright. But I hope you don't run out of GitHub action minutes before the end of the month! 😄
I'd run this cron once a week max 😊
True. It's probably excessive, thanks for pointing that out! Haha. I don't have enough github actions to notice, but thanks for letting me know that is a thing!!! I would have definitely hit that wall at some unfortunate point. 😅
Ah, we keep learning new things 🥰
That said, your profile repo is a public repo, which means GitHub may not deduct any minute at all, LOL.
But they must have an internal limit, otherwise people will go wild with these ☺️
I can see why now. "Evil laugh" 😂😅🤔🤣
It's so cool! I customized it a little for my GitHub profile. Thank you! 😸
that's so cooooool!!✨
Niiiiiiiiice. Love it!
This is a fun use of the API. I went down a bit of a rabbit hole with the followers endpoint this week and discovered something that might make the number itself even more interesting.
I pulled all of my follower data going back to 2017 and found that my account supposedly gained roughly 18,000 followers during 2026, while my posts received only about 14,300 total views. The follower acquisition rate also barely changed based on whether I published anything, and a surprisingly large percentage of the usernames had auto-generated-looking numeric or hex tails.
I can't prove those accounts are bots or generated accounts, so I wouldn't make that claim. But it did make me much more skeptical about treating the raw follower count as an audience/readership metric.
Your GitHub Action actually creates an interesting opportunity, though: since you're already running it periodically, you could save the follower IDs with each run rather than only the count. Over time, you'd get something the DEV dashboard doesn't really give you: actual follower additions and churn between snapshots.
I wrote up my API spelunking here if you're curious.
you can try this approach regarding bots/not bots dev.to/olgabraginskaya/whos-really...
I think I've seen your post before! Thanks for the reminder!!!
Yes! I actually started reading that article! I didnt have time to finish but it was definitely interesting!!!
niceee
Nice one
Thanks! ✨️
Nice works like a charm
Thanksss
Aww!!!! 💜
Very well done !
I just upset that I didn't think if this myself 😁
Aww haha. Maybe, make it somehow better? 🤔
I can try 😉
343 failed runs before the first success — that's commitment most people wouldn't bother with for a followers badge. The
git diff --quietcheck before committing is a nice touch, saves you from a commit history full of no-op runs. I'd add a failure notification step too though, so if the API key expires or the script breaks, you find out from a Slack ping instead of rediscovering it a year later.🤣🤣🤣 thank you @onizuka
So cool 😍
Hello @hadil , glad you like it! ✨️
it's good. but I've never understood why dev.to doesn't display followers...
I wondered that as well. Honestly, it doesn't bother me anymore. I think it actually adds quality by not making it some agenda based numbers game. Although we all like to feel validated! I get that. 🤔😅
thx!
Some comments may only be visible to logged-in visitors. Sign in to view all comments.