<?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: laing lii</title>
    <description>The latest articles on DEV Community by laing lii (@laing_lii_8c1214ffb0b60ec).</description>
    <link>https://dev.to/laing_lii_8c1214ffb0b60ec</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%2F4186156%2F9e6d1490-2dc4-4d23-9f91-5e3367596a88.png</url>
      <title>DEV Community: laing lii</title>
      <link>https://dev.to/laing_lii_8c1214ffb0b60ec</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/laing_lii_8c1214ffb0b60ec"/>
    <language>en</language>
    <item>
      <title>How I Got 200+ Visitors in 20 Days: Refactoring a Pure PHP Toolbox &amp; Adding Client-Side Security</title>
      <dc:creator>laing lii</dc:creator>
      <pubDate>Sun, 08 Nov 2026 01:23:46 +0000</pubDate>
      <link>https://dev.to/laing_lii_8c1214ffb0b60ec/how-i-got-200-visitors-in-20-days-refactoring-a-pure-php-toolbox-adding-client-side-security-kb6</link>
      <guid>https://dev.to/laing_lii_8c1214ffb0b60ec/how-i-got-200-visitors-in-20-days-refactoring-a-pure-php-toolbox-adding-client-side-security-kb6</guid>
      <description>&lt;p&gt;Hey DEV community! 👋&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frxud8co7cino8vmrwgs7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frxud8co7cino8vmrwgs7.png" alt=" " width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;About three weeks ago, I launched Site Tools Box (&lt;a href="https://sitetoolsbox.com)%E2%80%94a" rel="noopener noreferrer"&gt;https://sitetoolsbox.com)—a&lt;/a&gt; free, no-login toolbox for webmasters. It started as a simple side project, but after a surprising burst of traffic from Hacker News (200+ unique visitors in 20 days), I realized I needed to seriously level up the architecture.&lt;/p&gt;

&lt;p&gt;Here is a breakdown of the latest technical updates, what I learned, and how I handled the "Zero-Login" challenge.&lt;/p&gt;

&lt;p&gt;🚀 1. The Hybrid Architecture: Speed &amp;amp; Privacy First&lt;br&gt;
When building a toolbox, you face a classic dilemma:&lt;/p&gt;

&lt;p&gt;Option A: Do everything on the server (slower, heavy server load, privacy risks).&lt;/p&gt;

&lt;p&gt;Option B: Do everything in the browser (faster, but limits complex queries).&lt;/p&gt;

&lt;p&gt;I chose a Hybrid Architecture.&lt;br&gt;
For tools like the JSON Formatter, the logic runs 100% in Vanilla JavaScript. Data never leaves the user's machine.&lt;br&gt;
But for Bulk Domain Lookups, browsers can't query WHOIS/RDAP directly due to CORS and protocol limits. So, I built a server-side endpoint using native PHP's curl_multi. This allows parallel querying of up to 30 domains instantly, bypassing the sequential delays of traditional WHOIS lookups.&lt;/p&gt;

&lt;p&gt;🔒 2. UI/UX Overhaul: Daily Domains&lt;br&gt;
I recently added a "Daily Domains" feature, curating unregistered .com and .ai domains. I used to display them in clunky cards, but users got visual fatigue quickly.&lt;/p&gt;

&lt;p&gt;I refactored the front-end to use a compact, single-row list grouped by date. It drastically reduced cognitive load. To handle the affiliate redirects cleanly, I pass the domain dynamically via URL parameters:&lt;br&gt;
&lt;a href="https://www.namecheap.com/domains/registration/results/?domain=%7Bdomain%7D" rel="noopener noreferrer"&gt;https://www.namecheap.com/domains/registration/results/?domain={domain}&lt;/a&gt;&lt;br&gt;
🛡️ 3. The "Zero-Login" Security Challenge (MD5, SHA, Bcrypt)&lt;br&gt;
Many users asked for a Password Generator. But as a developer, I know that generating a password is only half the battle—you need to hash it for storage.&lt;/p&gt;

&lt;p&gt;I upgraded the tool to include:&lt;/p&gt;

&lt;p&gt;MD5 / SHA-256 / Base64: Processed entirely via crypto-js in the browser.&lt;/p&gt;

&lt;p&gt;Bcrypt Hashing: This was the tricky part. Bcrypt requires high CPU work (the "salt rounds"). Running it in JS is possible, but heavy.&lt;/p&gt;

&lt;p&gt;The Tech Stack I used:&lt;/p&gt;

&lt;p&gt;🎨 4. Avoiding the "Ugly System Alert"&lt;br&gt;
One thing I hate about older web apps is the default alert() when you copy text. I wrote a tiny smooth-copy function that changes the button state to a green "✅ Copied!" and reverts after 1.5 seconds. Small details like this make a tool feel like a modern SaaS.&lt;/p&gt;

&lt;p&gt;🚀 What's Next?&lt;br&gt;
I'm currently focusing on SEO optimization and trying to get the tool indexed by more search engines. The recent jump in traffic from Japan (thanks to a tech media mention) has also motivated me to keep the UI language-neutral and fast.&lt;/p&gt;

&lt;p&gt;If you want to check it out or give me some feedback on the architecture, here is the link:&lt;br&gt;
Live Tool: &lt;a href="https://sitetoolsbox.com" rel="noopener noreferrer"&gt;https://sitetoolsbox.com&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/kagouhui/site-tools-box" rel="noopener noreferrer"&gt;https://github.com/kagouhui/site-tools-box&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading! Happy coding! 💻&lt;/p&gt;

</description>
      <category>php</category>
      <category>javascript</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How I Built a Custom Anti-Spam Rate Limiter for My PHP Site (No Cloudflare</title>
      <dc:creator>laing lii</dc:creator>
      <pubDate>Thu, 05 Nov 2026 04:51:46 +0000</pubDate>
      <link>https://dev.to/laing_lii_8c1214ffb0b60ec/how-i-built-a-custom-anti-spam-rate-limiter-for-my-php-site-no-cloudflare-5a5d</link>
      <guid>https://dev.to/laing_lii_8c1214ffb0b60ec/how-i-built-a-custom-anti-spam-rate-limiter-for-my-php-site-no-cloudflare-5a5d</guid>
      <description>&lt;p&gt;If you run a free directory, the bots will find you. Within 48 hours of launching my free toolbox, I was getting hammered by automated scripts.&lt;/p&gt;

&lt;p&gt;I decided to ditch heavy WAF rules and build a custom rate limiter using pure vanilla PHP 8 with flat JSON files. No Redis, no database overhead.&lt;/p&gt;

&lt;p&gt;Here is how it works in 3 layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The Honeypot &amp;amp; Time Check&lt;br&gt;
I added a hidden input field (bots fill it, humans don't). If filled, instant ban. I also record page load time. If a user submits in under 5 seconds, they are a bot.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flat-File IP Rate Limiting&lt;br&gt;
Instead of querying the database on every attempt, I store IP timestamps in a JSON file (ip_limits.json). If an IP submits more than 3 times in 24 hours, I block them before any SQL runs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Server-Side Math CAPTCHA&lt;br&gt;
I generate two random numbers in a PHP session and ask the user to solve it (e.g., "What is 4 + 7?"). Scripts hate dynamic math.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Result:&lt;br&gt;
Spam submissions dropped to absolute zero. Real users don't notice a thing. A few lines of vanilla PHP saved me hours of headaches.&lt;/p&gt;

&lt;p&gt;I'm currently building Site Tools Box, a free ad-free platform with 20+ developer tools and an AI Text Humanizer. You can see this anti-spam system in action here:&lt;br&gt;
&lt;a href="https://dev.tourl"&gt;👉 sitetoolsbox.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have you ever fought a bot war on your own site? Let me know!&lt;/p&gt;

</description>
      <category>php</category>
      <category>webdev</category>
      <category>security</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I built a free AI text humanizer with dual-engine fallback. Need some brutal feedback on the output.</title>
      <dc:creator>laing lii</dc:creator>
      <pubDate>Wed, 04 Nov 2026 00:19:55 +0000</pubDate>
      <link>https://dev.to/laing_lii_8c1214ffb0b60ec/building-a-resilient-ai-text-humanizer-with-dual-engine-fallback-php-openrouter-2b1</link>
      <guid>https://dev.to/laing_lii_8c1214ffb0b60ec/building-a-resilient-ai-text-humanizer-with-dual-engine-fallback-php-openrouter-2b1</guid>
      <description>&lt;p&gt;Hey everyone,&lt;/p&gt;

&lt;p&gt;I got tired of "free" AI tools that actually charge you after 200 words. So I built my own over the weekend. It's a dual-engine setup (OpenRouter + SiliconFlow) written in pure PHP so it shouldn't crash when the API gets rate-limited.&lt;/p&gt;

&lt;p&gt;I also added a strict daily limit (5 uses per IP) because a botnet attacked my endpoint 50 times right after I launched it.&lt;/p&gt;

&lt;p&gt;I bundled it with 20+ other webmaster tools (WHOIS, DNS, JSON, etc). I'm mainly looking for feedback on the humanizer's output—does it actually sound natural to you?&lt;/p&gt;

&lt;p&gt;If you want to test it out, just type "sitetoolsbox.com" into your browser, the humanizer is in the AI section.&lt;/p&gt;

&lt;p&gt;What's the biggest pain point you usually hit with AI detectors? Would love to know what to improve.&lt;/p&gt;

</description>
      <category>php</category>
      <category>ai</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
    <item>
      <title>The Silent Killer of Uptime: Why You Must Master DNS Lookups</title>
      <dc:creator>laing lii</dc:creator>
      <pubDate>Tue, 03 Nov 2026 00:33:04 +0000</pubDate>
      <link>https://dev.to/laing_lii_8c1214ffb0b60ec/the-silent-killer-of-uptime-why-you-must-master-dns-lookups-b7f</link>
      <guid>https://dev.to/laing_lii_8c1214ffb0b60ec/the-silent-killer-of-uptime-why-you-must-master-dns-lookups-b7f</guid>
      <description>&lt;p&gt;If you manage servers, deploy microservices, or just run a WordPress site, you've probably experienced it: A sudden, unexplainable outage. The server is running. The CPU is at 10%. The firewall is open. Yet, users are reporting that your site is completely unreachable.&lt;/p&gt;

&lt;p&gt;Nine times out of ten, the problem isn't your code. It's the invisible routing layer of the internet: &lt;strong&gt;DNS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Most developers treat DNS as a "set it and forget it" configuration—a one-time A record update in their domain registrar. But DNS is incredibly fragile. Here is why you need to actively monitor it, and how to diagnose it in seconds.&lt;/p&gt;

&lt;h3&gt;1. The CNAME Chain Reaction&lt;/h3&gt;

&lt;p&gt;Many of us use CNAME records to point subdomains to third-party services (like an AWS Load Balancer, a Shopify store, or a Mailchimp server). The danger here is the "chain." If that upstream provider updates their IP address and breaks the chain, your subdomain goes dark.&lt;/p&gt;

&lt;p&gt;You can't just `ping` the domain; you need to query the exact record type. Our free &lt;strong&gt;&lt;a href="https://sitetoolsbox.com/tool.php?slug=dns" rel="noopener noreferrer"&gt;DNS Lookup Tool&lt;/a&gt;&lt;/strong&gt; allows you to instantly query the CNAME and trace where it's pointing. If it resolves to an IP that you don't recognize, you've found your culprit.&lt;/p&gt;

&lt;h3&gt;2. The "Propagation is Slow" Excuse&lt;/h3&gt;

&lt;p&gt;You changed your A record 3 hours ago, but half your users are still hitting the old server. You might think it's just "normal propagation." But if you are using Cloudflare or AWS Route 53, updates should be near-instant.&lt;/p&gt;

&lt;p&gt;If you suspect slow propagation, run a query against the specific nameservers using our tool. You can check the &lt;strong&gt;NS records&lt;/strong&gt; and the &lt;strong&gt;SOA records&lt;/strong&gt; to see exactly what the authoritative name server is broadcasting. It gives you the hard truth before you blame the ISP.&lt;/p&gt;

&lt;h3&gt;3. The Silent Email Killer (MX &amp;amp; SPF)&lt;/h3&gt;

&lt;p&gt;Your website loads fine, but your contact form emails are bouncing, or customers aren't receiving password resets. This is a classic MX (Mail Exchanger) misconfiguration. Or worse, your TXT records (SPF/DKIM) are missing, causing Google and Microsoft to instantly trash your transactional emails.&lt;/p&gt;

&lt;p&gt;A DNS Lookup isn't just for web traffic. Querying the &lt;strong&gt;MX&lt;/strong&gt; and &lt;strong&gt;TXT&lt;/strong&gt; records ensures your mail routing and domain verification are bulletproof.&lt;/p&gt;

&lt;h3&gt;How to Diagnose Any DNS Issue in 5 Seconds&lt;/h3&gt;

&lt;p&gt;Stop opening a terminal and typing `nslookup` or `dig` blindly. It's clunky, and if you're on a restricted network or VPN, the results might be cached locally and give you a false reading.&lt;/p&gt;

&lt;p&gt;Use our web-based &lt;strong&gt;&lt;a href="https://sitetoolsbox.com/tool.php?slug=dns" rel="noopener noreferrer"&gt;DNS Lookup Tool&lt;/a&gt;&lt;/strong&gt;. It queries from our high-availability infrastructure, meaning you get a clean, uncached, real-world view of your DNS records.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features you can use right now:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Check A and AAAA records to verify dual-stack (IPv4/IPv6) configurations.&lt;/li&gt;
    &lt;li&gt;Verify CNAME aliases to prevent routing loops.&lt;/li&gt;
    &lt;li&gt;Validate TXT records for SPF domain verification.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you are a sysadmin fighting a 2 AM outage or a webmaster setting up a new domain, DNS is your first line of defense. Bookmark the tool, and save yourself hours of hair-pulling.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://sitetoolsbox.com/tool.php?slug=dns" rel="noopener noreferrer"&gt;Run a Free DNS Lookup Now →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>dnslookup</category>
      <category>webdev</category>
      <category>sysadmin</category>
      <category>networktroubleshooting</category>
    </item>
    <item>
      <title>Stop Using Slow APIs: The Right Way to Bulk Check HTTP Statuses (50+ URLs in Seconds)</title>
      <dc:creator>laing lii</dc:creator>
      <pubDate>Sat, 31 Oct 2026 06:03:17 +0000</pubDate>
      <link>https://dev.to/laing_lii_8c1214ffb0b60ec/stop-using-slow-apis-the-right-way-to-bulk-check-http-statuses-50-urls-in-seconds-b62</link>
      <guid>https://dev.to/laing_lii_8c1214ffb0b60ec/stop-using-slow-apis-the-right-way-to-bulk-check-http-statuses-50-urls-in-seconds-b62</guid>
      <description>&lt;p&gt;Last week, I found myself staring at a dead-links report for an old client project. Over 300 pages. I needed to know which URLs were returning 404s, which ones were silently redirecting, and which ones had just given up entirely.&lt;/p&gt;

&lt;p&gt;My first instinct was to write a quick loop in Node.js using &lt;code&gt;fetch&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;I hit two massive walls immediately:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Rate Limit / IP Ban wall:&lt;/strong&gt; After about 15 requests, the target servers started dropping my connection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Timeout wall:&lt;/strong&gt; My script hung for 5 minutes because three random URLs just never responded.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you've ever tried to bulk check HTTP statuses at scale, you know the pain. So, let me save you a few hours of frustration.&lt;/p&gt;

&lt;p&gt;Here is the breakdown of how this &lt;em&gt;should&lt;/em&gt; work, and a free tool I started using to bypass the headache entirely.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Naive Approach (And Why It Fails)
&lt;/h3&gt;

&lt;p&gt;Here’s how most of us start writing a bulk HTTP checker:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
javascript
// DON'T DO THIS FOR BULK CHECKS
async function checkUrls(urls) {
  for (const url of urls) {
    try {
      const res = await fetch(url, { method: 'HEAD' });
      console.log(url, res.status);
    } catch (e) {
      console.log(url, 'Error');
    }
  }
}

This is a disaster for a few reasons:

HEAD isn't always supported: Some servers block HEAD requests and only return a valid 200 for GET.

No Concurrency Control: If you use Promise.all(), you’ll fire 50 requests at once and your IP will get blocked by Cloudflare instantly.

No Timeouts: A single hanging URL will block your entire script.

The "Developer" Way to Fix It
To do this properly in a script, you need to implement:

Connection Pooling / Semaphores (to limit concurrency to ~5 requests at a time).

Custom AbortControllers (to kill requests after 5 seconds).

User-Agent spoofing (so it looks like a real browser).

It’s a fun technical exercise, but when you’re on a deadline and just need the data, writing this whole infrastructure is a waste of time.

The Alternative: Automate It Without the Code
When I realized I was spending more time debugging my scraper than actually auditing the site, I switched to using a bulk HTTP checker tool I found online.

I’ve been using Bulk HTTP Checker on Site Tools Box.

It’s a lightweight, backend-optimized tool that handles all the heavy lifting for you. You can paste up to 50 URLs, hit run, and it handles the concurrency, redirects, and timeouts instantly.

It returns a clean list of:

Status Codes (200, 301, 404, 500)

Redirect chains (where it actually goes)

Response times

And because it’s built for developers, it doesn't try to sell you a $29/month subscription for a simple check.

One Last Pro-Tip for SEO / Auditing
If you have a sitemap and want to find out which specific pages on your site are broken, you don't even need to copy-paste manually. Just use the Dead Link Checker on Site Tools Box. It scans a page, crawls the outgoing links, and highlights any broken ones in red. I used it to find 3 dead links in my footer that had been silently 404-ing for months.

Don't waste your weekends writing semaphores for a script you'll only use once. Optimize your workflow, and get back to writing actual code.

Have you ever accidentally DoS'd a server with a Promise.all() loop? Let me know in the comments. We've all been there.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>productivity</category>
      <category>nocode</category>
    </item>
    <item>
      <title>Why I Dumped GA4 to Build a 2KB Privacy-First Stats System (and Caught a Fake "Big Tech" Company)</title>
      <dc:creator>laing lii</dc:creator>
      <pubDate>Fri, 30 Oct 2026 00:07:28 +0000</pubDate>
      <link>https://dev.to/laing_lii_8c1214ffb0b60ec/why-i-dumped-ga4-to-build-a-2kb-privacy-first-stats-system-and-caught-a-fake-big-tech-company-3fgm</link>
      <guid>https://dev.to/laing_lii_8c1214ffb0b60ec/why-i-dumped-ga4-to-build-a-2kb-privacy-first-stats-system-and-caught-a-fake-big-tech-company-3fgm</guid>
      <description>&lt;p&gt;When I launched my side project—a curated directory for webmaster and SEO tools—I did what everyone does: I slapped Google Analytics (GA4) on it. &lt;/p&gt;

&lt;p&gt;But within a week, I was frustrated. GA4 felt bloated, it added heavy JS files to my tiny server (2-core, 2GB RAM), and the "bot filtering" was practically non-existent. I was getting hundreds of "visits" a day, but my PayPal account remained empty.&lt;/p&gt;

&lt;p&gt;I realized I needed a brutal, no-nonsense way to see exactly &lt;em&gt;who&lt;/em&gt; was hitting my site.&lt;/p&gt;

&lt;p&gt;So, I deleted GA4 and built my own analytics system from scratch. Here is how it went, and the hilarious trap it helped me uncover.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture: Keep It Dead Simple
&lt;/h2&gt;

&lt;p&gt;I didn't want to spin up a heavy MySQL database just for logging. I wanted something I could read with my own eyes.&lt;/p&gt;

&lt;p&gt;I decided to use &lt;strong&gt;JSONL (JSON Lines)&lt;/strong&gt; and a tiny PHP endpoint.&lt;/p&gt;

&lt;p&gt;Here is how the data flows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A lightweight JS &lt;code&gt;fetch()&lt;/code&gt; on the main site sends a &lt;code&gt;POST&lt;/code&gt; request to my stats subdomain.&lt;/li&gt;
&lt;li&gt;The PHP API receives the data (URL, Referer, User-Agent, IP).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Core Logic:&lt;/strong&gt; The PHP script regex-matches the User-Agent against a list of known bot strings (&lt;code&gt;googlebot&lt;/code&gt;, &lt;code&gt;ahrefs&lt;/code&gt;, &lt;code&gt;python&lt;/code&gt;, &lt;code&gt;crawl&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;If it's a bot, it's flagged as &lt;code&gt;is_spider: 1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The data is appended to a daily text file: &lt;code&gt;log_2026-10-30.jsonl&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is what a raw log entry looks like:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
json
{"time":"15:41:56","ip":"43.128.87.232","country":"France","url":"/pay.php","ref":"","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X...)","is_spider":0}

The Moment It Paid Off: Catching the "Fake Big Tech"
Because I now have the raw IP and User-Agent, my dashboard separates the noise from the real people.

Yesterday, my stats showed a "Real Human" hitting my /pay.php page. I got excited—someone was actually looking to pay for my premium listing!

But then, I noticed something strange in the logs. A company called "Logipax" submitted their site. Their landing page was incredible. It claimed to be a top-tier passenger transport SaaS operating "Since 1995", complete with a London map background and enterprise pricing.

It looked like a massive, established European company. Why would they submit to a new, tiny directory?

Curiosity got the better of me. I pulled their IP from my JSONL log and ran a quick WHOIS lookup.

The result was hilarious.

The domain logipax.io was registered just 4 days ago.

They had built a highly polished UI, written fake enterprise copy, and spammed every directory on the web to build SEO backlinks. If I had been using GA4, I would have just seen a "session from the UK" and approved them without thinking.

(Insert your screenshot of the WHOIS lookup here)

The Takeaway for Indie Hackers
Building this tiny 2KB system changed how I view web traffic. It's no longer just a number on a chart; it's a real story.

GA4 is overkill for side projects. If you just want to know if real humans are visiting, build your own logger. It's a fun weekend project.

Bots are loud, humans are quiet. 70% of my daily traffic is just Ahrefs and Googlebot. Seeing this visually stopped me from stressing out over "zero traffic."

Data ownership is freedom. I can run custom SQL queries, filter by country, and spot fake traffic instantly, all without paying a monthly SaaS fee.

If you're building something small, don't be afraid to strip things down. The best stack is the one you actually understand.

(If you want to see the final result or find some cool dev tools, you can check out my project here: Site Tools Box.)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>webdev</category>
      <category>seo</category>
      <category>security</category>
      <category>showdev</category>
    </item>
    <item>
      <title>How I Built a Bulk Domain Availability Checker with RDAP and Automated Scoring</title>
      <dc:creator>laing lii</dc:creator>
      <pubDate>Wed, 28 Oct 2026 02:23:31 +0000</pubDate>
      <link>https://dev.to/laing_lii_8c1214ffb0b60ec/how-i-built-a-bulk-domain-availability-checker-with-rdap-and-automated-scoring-32h4</link>
      <guid>https://dev.to/laing_lii_8c1214ffb0b60ec/how-i-built-a-bulk-domain-availability-checker-with-rdap-and-automated-scoring-32h4</guid>
      <description>&lt;p&gt;I recently found myself needing to buy a short, brandable domain for a side project. I spent hours typing names into GoDaddy, only to get frustrated by the slow interface and the constant upsells.&lt;/p&gt;

&lt;p&gt;As a developer, I thought: "Why not just query the RDAP registries directly and score the domains algorithmically?"&lt;/p&gt;

&lt;p&gt;So I built a free tool to do exactly that. Here is how it works and why RDAP is the future of domain checking.&lt;/p&gt;

&lt;p&gt;The Problem with Traditional WHOIS&lt;br&gt;
Most domain tools still use standard WHOIS (Port 43). It is plain text, rate-limits aggressively, and often gets blocked by registrars.&lt;/p&gt;

&lt;p&gt;RDAP (Registration Data Access Protocol) is the modern, ICANN-mandated replacement. It returns structured JSON and uses standard HTTPS status codes:&lt;/p&gt;

&lt;p&gt;200 OK = Domain is registered.&lt;/p&gt;

&lt;p&gt;404 Not Found = Domain is available.&lt;/p&gt;

&lt;p&gt;This makes it incredibly easy for developers to query concurrently without getting blocked.&lt;/p&gt;

&lt;p&gt;The Architecture&lt;br&gt;
I built a tool that lets you paste up to 50 domains (one per line). Instead of firing 50 requests at once and getting rate-limited, the backend processes them in small concurrent batches (using curl_multi in PHP).&lt;/p&gt;

&lt;p&gt;Here is what the result dashboard looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft0jqkssyzuoetmkzhfc8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft0jqkssyzuoetmkzhfc8.png" alt=" " width="800" height="858"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Domain Scoring Algorithm&lt;br&gt;
Just knowing if a domain is available isn't enough. You need to know if it's actually good.&lt;/p&gt;

&lt;p&gt;I wrote an algorithmic scoring system (0-100) that evaluates domains across 5 dimensions:&lt;/p&gt;

&lt;p&gt;Extension (TLD): .com, .ai, .io score highest.&lt;/p&gt;

&lt;p&gt;Length: Short names (4-5 letters) get exponential value.&lt;/p&gt;

&lt;p&gt;Pronounceability: It analyzes vowel-consonant patterns (CVCV) to ensure it's easy to say.&lt;/p&gt;

&lt;p&gt;Meaning: Checks against a built-in dictionary of common English words.&lt;/p&gt;

&lt;p&gt;Brand Fit: Looks for industry prefixes like AI, tech, or e-commerce.&lt;/p&gt;

&lt;p&gt;If a domain scores 80+, it's highlighted in red as a 🔥 High Value domain. You can copy all the high-value results to your clipboard with one click.&lt;/p&gt;

&lt;p&gt;Why I Made It Free (For Now)&lt;br&gt;
I'm currently offering single checks for free. Building this has taught me a lot about RDAP and concurrent API handling.&lt;/p&gt;

&lt;p&gt;If you want to try it out, you can check it here:&lt;br&gt;
👉 Site Tools Box - Domain Availability Check&lt;/p&gt;

&lt;p&gt;(Note: The bulk check feature is currently locked behind a Pro tier while I optimize the server load, but single checks are 100% free).&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>api</category>
      <category>nocode</category>
    </item>
    <item>
      <title>Iterating on a Domain Checker: Adding Timestamps, Sources, and IANA Bootstrap</title>
      <dc:creator>laing lii</dc:creator>
      <pubDate>Tue, 27 Oct 2026 03:20:23 +0000</pubDate>
      <link>https://dev.to/laing_lii_8c1214ffb0b60ec/iterating-on-a-domain-checker-adding-timestamps-sources-and-iana-bootstrap-591l</link>
      <guid>https://dev.to/laing_lii_8c1214ffb0b60ec/iterating-on-a-domain-checker-adding-timestamps-sources-and-iana-bootstrap-591l</guid>
      <description>&lt;p&gt;A few days ago, I wrote a post about how I built a bulk domain availability checker using PHP and RDAP (instead of the traditional WHOIS protocol) over at &lt;a href="https://sitetoolsbox.com" rel="noopener noreferrer"&gt;Site Tools Box&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;To my surprise, the post got some fantastic technical feedback from the community. One comment from a developer named Furqan completely nailed some of the pain points I was already struggling with in production.&lt;/p&gt;

&lt;p&gt;Here are the three brilliant suggestions he made, and how I'm currently implementing them to make the tool more reliable.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The "Premium Domain" Illusion: Why a 404 is Just a Hint
&lt;/h2&gt;

&lt;p&gt;In my previous post, I mentioned that querying RDAP returns a &lt;code&gt;404 Not Found&lt;/code&gt; if a domain is available, and &lt;code&gt;200 OK&lt;/code&gt; if it's registered. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem?&lt;/strong&gt; Premium and reserved domains. Sometimes, a registry will return a &lt;code&gt;404&lt;/code&gt; because it's technically unregistered, but it's actually a premium name that requires a 5-figure price tag at the registrar.&lt;/p&gt;

&lt;p&gt;Furqan's suggestion: &lt;strong&gt;Flag 404s as "Likely Available" instead of a hard "Yes".&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a brilliant UX change. I'm now updating the frontend to display a "Likely Available" badge with a tooltip explaining that premium domains can sometimes show as available but are locked behind a premium price wall.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Transparency: Adding "Last Checked" Timestamps and Sources
&lt;/h2&gt;

&lt;p&gt;Right now, when you check a domain on &lt;a href="https://sitetoolsbox.com/tool.php?slug=domain_check" rel="noopener noreferrer"&gt;Site Tools Box&lt;/a&gt;, you get the result, but you don't know &lt;em&gt;when&lt;/em&gt; it was checked or &lt;em&gt;where&lt;/em&gt; the data came from.&lt;/p&gt;

&lt;p&gt;Furqan suggested adding a "last checked" timestamp and the source (RDAP vs. WHOIS). &lt;/p&gt;

&lt;p&gt;This is crucial for debugging. When doing bulk checks of 100+ domains, network timeouts happen. By displaying the exact timestamp and the specific RDAP server endpoint used (e.g., &lt;code&gt;rdap.verisign.com&lt;/code&gt;), users can immediately tell if a result is stale or if the query failed.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Ditching the Hardcoded Map for IANA Bootstrap
&lt;/h2&gt;

&lt;p&gt;In my original PHP code, I had a massive &lt;code&gt;switch&lt;/code&gt; statement and array mapping TLDs to their respective RDAP servers (e.g., &lt;code&gt;.com&lt;/code&gt; -&amp;gt; Verisign, &lt;code&gt;.io&lt;/code&gt; -&amp;gt; Identity Digital). &lt;/p&gt;

&lt;p&gt;Furqan pointed out the obvious scaling issue: &lt;strong&gt;This hardcoded map is a nightmare to maintain.&lt;/strong&gt; What happens when a new TLD like &lt;code&gt;.xyz&lt;/code&gt; or &lt;code&gt;.ai&lt;/code&gt; changes its registry?&lt;/p&gt;

&lt;p&gt;His solution: &lt;strong&gt;Use IANA's Bootstrap file.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;IANA provides a public JSON file (&lt;code&gt;https://data.iana.org/rdap/dns.json&lt;/code&gt;) that automatically maps every TLD to its current RDAP endpoint. I'm currently rewriting my backend to fetch this file, cache it locally, and dynamically route queries. This means the tool will automatically support new TLDs without me lifting a finger.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
php
// Pseudo-code for the new dynamic approach
$bootstrapUrl = 'https://data.iana.org/rdap/dns.json';
$bootstrapData = json_decode(file_get_contents($bootstrapUrl), true);

// Dynamically find the endpoint for .com
foreach ($bootstrapData['services'] as $service) {
    if (in_array('com', $service[0])) {
        $endpoint = $service[1][0];
        break;
    }
}



The Takeaway: Build in Public, Iterate Fast
This whole experience has been a masterclass in building in public. The feedback from the dev community is invaluable. What you think is a solid MVP might have fatal edge cases in the real world.

If you want to see the updated tool (and test the new features as they roll out), you can check it out here: Free Domain Availability Checker.

Have you ever built a tool that had to handle messy edge cases like premium domains or dynamic TLD routing? Let me know in the comments!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>php</category>
      <category>webdev</category>
      <category>seo</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Silent SEO Killer: How I Lost 30% of Organic Traffic on a Site Migration</title>
      <dc:creator>laing lii</dc:creator>
      <pubDate>Sun, 25 Oct 2026 04:36:24 +0000</pubDate>
      <link>https://dev.to/laing_lii_8c1214ffb0b60ec/the-silent-seo-killer-how-i-lost-30-of-organic-traffic-on-a-site-migration-4gj5</link>
      <guid>https://dev.to/laing_lii_8c1214ffb0b60ec/the-silent-seo-killer-how-i-lost-30-of-organic-traffic-on-a-site-migration-4gj5</guid>
      <description>&lt;p&gt;We’ve all been there. You migrate a site to a new server or change your permalinks, feeling confident because the new UI looks great. Then, a week later, you open Google Search Console and see a massive cliff: &lt;strong&gt;a 30% drop in organic traffic.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A migration is never just about moving files. It’s a complex DNS and routing operation. When it goes wrong, search engines don't forgive easily. &lt;/p&gt;

&lt;p&gt;After spending three days debugging a client's botched migration, I realized that 90% of post-migration traffic drops are caused by four easily preventable technical issues. Here is the checklist I now strictly follow before and after any site move.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Silent Fail: Broken Internal Links (404s)
&lt;/h2&gt;

&lt;p&gt;When you change URLs, it's easy to miss internal links in old blog posts or documentation. If a crawler hits a 404 page, it stops traversing that path. Too many 404s, and your site's crawl budget takes a hit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to audit:&lt;/strong&gt; Don't just click around manually. You need to extract all links from a page and check their HTTP response codes. &lt;br&gt;
Instead of writing a complex Python script with &lt;code&gt;requests&lt;/code&gt; and &lt;code&gt;BeautifulSoup&lt;/code&gt;, I usually run a quick batch scan. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Example: I use the bulk dead link scanner on &lt;a href="https://sitetoolsbox.com" rel="noopener noreferrer"&gt;Site Tools Box&lt;/a&gt; to scan the top 50 pages of the site. It crawls the DOM, sends HEAD requests to every anchor tag, and spits out a list of any 404s or 500s in seconds.)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The TTL Trap: DNS Propagation and AAAA Records
&lt;/h2&gt;

&lt;p&gt;You updated the A record to the new server IP, but did you check the AAAA record? If you have an IPv6 record pointing to the old server, users on IPv6 networks (which is a huge percentage of mobile traffic) will still hit the dead server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to audit:&lt;/strong&gt; Use a thorough DNS lookup. You need to verify A, CNAME, MX (don't forget emails!), and TXT records. &lt;br&gt;
Before you switch the nameservers, lower your TTL (Time To Live) to 300 seconds at least 24 hours in advance. This ensures that when you make the switch, global ISPs pick up the change instantly rather than caching the old IP for 48 hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The Redirect Chain Nightmare
&lt;/h2&gt;

&lt;p&gt;You moved from &lt;code&gt;http://website.com/old-post&lt;/code&gt; to &lt;code&gt;https://website.com/new-post&lt;/code&gt;. &lt;br&gt;
If your redirects look like &lt;code&gt;http&lt;/code&gt; -&amp;gt; &lt;code&gt;https&lt;/code&gt; -&amp;gt; &lt;code&gt;www&lt;/code&gt; -&amp;gt; &lt;code&gt;new-url&lt;/code&gt;, you are burning server resources and leaking PageRank with every hop. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; Every old URL should 301 redirect to its final destination in &lt;strong&gt;exactly one hop&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to audit:&lt;/strong&gt; Write down your 10 most valuable URLs (highest traffic pages). Check their status codes. &lt;br&gt;
You can use an HTTP header/status checker to see the exact response and how long it takes the server to respond. If it's a 301, ensure &lt;code&gt;Location&lt;/code&gt; headers point directly to the final HTTPS URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The Pre-Migration Domain Vetting
&lt;/h2&gt;

&lt;p&gt;If you are migrating to a brand new domain, buying a clean domain is half the battle. If the previous owner was running a PBN (Private Blog Network) or was penalized by Google, your traffic will never recover.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to audit:&lt;/strong&gt; Before you even pay for a domain, do a deep Whois lookup. You need to check the creation date, the registrar, and most importantly, whether the domain has been dropped and re-registered multiple times. &lt;br&gt;
A quick RDAP lookup is usually enough to reveal the registration history. If it was created 3 weeks ago but has 10,000 backlinks, run away.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary Checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Lower DNS TTL 24 hours prior.&lt;/li&gt;
&lt;li&gt;Verify A, AAAA, and CNAME records.&lt;/li&gt;
&lt;li&gt;Ensure single-hop 301 redirects for all legacy URLs.&lt;/li&gt;
&lt;li&gt;Crawl the entire new site to find dead internal links.&lt;/li&gt;
&lt;li&gt;Submit the new &lt;code&gt;sitemap.xml&lt;/code&gt; to Google Search Console immediately.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The Takeaway&lt;/strong&gt;&lt;br&gt;
A successful migration isn't a &lt;em&gt;visual&lt;/em&gt; success; it's a &lt;em&gt;routing&lt;/em&gt; success. Take 30 minutes to run these technical diagnostics before you hit "deploy" in production. Your organic traffic (and your client) will thank you.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Stop Guessing: A Developer's Guide to Debugging HTTP Headers with cURL</title>
      <dc:creator>laing lii</dc:creator>
      <pubDate>Fri, 23 Oct 2026 01:04:00 +0000</pubDate>
      <link>https://dev.to/laing_lii_8c1214ffb0b60ec/stop-guessing-a-developers-guide-to-debugging-http-headers-with-curl-4j1n</link>
      <guid>https://dev.to/laing_lii_8c1214ffb0b60ec/stop-guessing-a-developers-guide-to-debugging-http-headers-with-curl-4j1n</guid>
      <description>&lt;p&gt;I've lost count of how many times I've spent hours debugging an API integration, only to realize the issue wasn't my code, but a silent 502 Bad Gateway or a misconfigured Content-Type header.&lt;/p&gt;

&lt;p&gt;When a web application fails silently, the first thing you should do is look at the raw HTTP response. Browsers abstract this away from us, so as developers, we need to drop down to the network layer.&lt;/p&gt;

&lt;p&gt;Here is my standard workflow for debugging APIs using cURL, and how to do it faster when you don't have terminal access.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Basics: Fetching Headers Only
When debugging, you usually don't care about the entire HTML body. You just want the headers. Using -I (or --head) tells cURL to only fetch the headers:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;bash&lt;br&gt;
curl -I &lt;a href="https://api.example.com/v1/users" rel="noopener noreferrer"&gt;https://api.example.com/v1/users&lt;/a&gt;&lt;br&gt;
This will return the HTTP status code (200, 404, 500), the server type, cache control, and crucially, the Content-Type.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Following Redirects (301 vs 302)
If you are migrating a site or testing an API endpoint, you need to know if the server is redirecting you. By default, cURL does not follow redirects.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you see a 301 or 302 in the output, add the -L flag:&lt;/p&gt;

&lt;p&gt;bash&lt;br&gt;
curl -IL &lt;a href="https://example.com/old-endpoint" rel="noopener noreferrer"&gt;https://example.com/old-endpoint&lt;/a&gt;&lt;br&gt;
This will follow the redirect chain and show you the final status code. If you see an infinite redirect loop, this is the fastest way to catch it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Inspecting the Exact Request/Response
Sometimes you need to see exactly what headers your client is sending. Maybe you forgot the Authorization token, or your Accept header is wrong.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The -v (verbose) flag is your best friend:&lt;/p&gt;

&lt;p&gt;bash&lt;br&gt;
curl -v -X POST &lt;a href="https://api.example.com/v1/login" rel="noopener noreferrer"&gt;https://api.example.com/v1/login&lt;/a&gt; \&lt;br&gt;
  -H "Content-Type: application/json" \&lt;br&gt;
  -d '{"user":"admin","pass":"secret"}'&lt;br&gt;
The output will show lines starting with &amp;gt; (what cURL sent) and &amp;lt; (what the server returned). This instantly reveals if you are missing a bearer token or sending malformed JSON.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Problem: When You Don't Have a Terminal
As developers, we spend most of our time in the terminal. But what happens when you are debugging on a mobile device, or you just want a quick check without opening a new tab?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I got tired of trying to remember cURL flags and writing out long commands every time, so I built a couple of lightweight tools for my own workflow and put them on Site Tools Box (no sign-ups, no ads).&lt;/p&gt;

&lt;p&gt;For single URLs: I use the HTTP Status Checker. It gives you the status code, response time, and headers in a clean UI.&lt;/p&gt;

&lt;p&gt;For bulk checking: If you have a list of URLs (like checking a sitemap for 404s), use the Bulk HTTP Checker. It runs in your browser and checks up to 20 URLs at once via a CORS proxy.&lt;/p&gt;

&lt;p&gt;Wrapping Up&lt;br&gt;
Debugging is 90% observation and 10% fixing. Before you start tearing apart your frontend code, verify the HTTP layer. A quick cURL command or a fast online check can save you hours of frustration.&lt;/p&gt;

&lt;p&gt;What's your go-to cURL trick for debugging? Let me know in the comments!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>api</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Stop Manually Checking Broken Links: A Developer's Guide to Automated 404 Hunting</title>
      <dc:creator>laing lii</dc:creator>
      <pubDate>Thu, 22 Oct 2026 00:57:15 +0000</pubDate>
      <link>https://dev.to/laing_lii_8c1214ffb0b60ec/stop-manually-checking-broken-links-a-developers-guide-to-automated-404-hunting-4a0m</link>
      <guid>https://dev.to/laing_lii_8c1214ffb0b60ec/stop-manually-checking-broken-links-a-developers-guide-to-automated-404-hunting-4a0m</guid>
      <description>&lt;p&gt;I used to have a really bad habit. After deploying a major update to a client's site or migrating a blog to a new CMS, I would click through a few pages, assume everything worked, and close my laptop.&lt;/p&gt;

&lt;p&gt;Then, a week later, Google Search Console would light up with 404 errors, or a user would email me: "Hey, the link to your pricing page is broken."&lt;/p&gt;

&lt;p&gt;Broken links are a silent killer. They destroy your SEO, frustrate users, and make your site look unmaintained. But here's the thing: Manually checking links is a waste of your time as a developer.&lt;/p&gt;

&lt;p&gt;Here is how I stopped clicking links manually and started automating the 404 hunting process.&lt;/p&gt;

&lt;p&gt;The Problem with "Simple" Link Checkers&lt;br&gt;
If you Google "broken link checker," you'll find hundreds of tools. But most of them have fatal flaws for developers:&lt;/p&gt;

&lt;p&gt;They require installing a massive desktop app (looking at you, Screaming Frog). It's great for deep audits, but I don't want to launch a heavy Java app just to check 20 links.&lt;/p&gt;

&lt;p&gt;They are filled with ads and require sign-ups. I don't want to hand over my email address just to check an HTTP status code.&lt;/p&gt;

&lt;p&gt;The free tier limits you to 5 URLs.&lt;/p&gt;

&lt;p&gt;Approach 1: The cURL Bash Script (For Server-Side Checking)&lt;br&gt;
If you have terminal access, you can write a quick Bash script to check a list of URLs using curl. Here is a simple script that reads a text file of URLs (urls.txt) and spits out the HTTP status code for each:&lt;/p&gt;

&lt;p&gt;bash&lt;/p&gt;

&lt;h1&gt;
  
  
  !/bin/bash
&lt;/h1&gt;

&lt;h1&gt;
  
  
  Read from urls.txt
&lt;/h1&gt;

&lt;p&gt;while read -r url; do&lt;br&gt;
  # -o /dev/null discards the HTML body&lt;br&gt;
  # -s silences the progress bar&lt;br&gt;
  # -w writes out the HTTP status code&lt;br&gt;
  # -I fetches only the headers&lt;br&gt;
  status=$(curl -o /dev/null -s -w "%{http_code}" -I "$url")&lt;/p&gt;

&lt;p&gt;if [ "$status" -ne 200 ]; then&lt;br&gt;
    echo "❌ [$status] $url"&lt;br&gt;
  else&lt;br&gt;
    echo "✅ [200] $url"&lt;br&gt;
  fi&lt;br&gt;
done &amp;lt; urls.txt&lt;br&gt;
This is fast and doesn't require any third-party API. However, if you are checking URLs that are behind Cloudflare or have strict WAF rules, curl might get blocked (returning a 403 instead of the real status).&lt;/p&gt;

&lt;p&gt;Approach 2: The Client-Side Browser Check (For Quick Audits)&lt;br&gt;
Sometimes I just want to check a handful of links on the fly without opening a terminal. But doing this in the browser has a massive hurdle: CORS (Cross-Origin Resource Sharing). Browsers block JavaScript from making arbitrary HTTP requests to external domains.&lt;/p&gt;

&lt;p&gt;To bypass this, you can use a public CORS proxy like allorigins.win to fetch the URL and return the status code via frontend JS:&lt;/p&gt;

&lt;p&gt;javascript&lt;br&gt;
async function checkLink(url) {&lt;br&gt;
  const proxyUrl = &lt;code&gt;https://api.allorigins.win/get?url=${encodeURIComponent(url)}&lt;/code&gt;;&lt;/p&gt;

&lt;p&gt;try {&lt;br&gt;
    const response = await fetch(proxyUrl);&lt;br&gt;
    const data = await response.json();&lt;br&gt;
    const status = data.status?.http_code || 0;&lt;br&gt;
    return status;&lt;br&gt;
  } catch (err) {&lt;br&gt;
    return 'Error/Timeout';&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
Approach 3: Just Use a Fast, No-Signup Tool&lt;br&gt;
Writing scripts is fun, but when I'm in the middle of a deployment, I just want a clean interface to do a quick check.&lt;/p&gt;

&lt;p&gt;I got tired of navigating through ad-ridden sites, so I actually built a couple of lightweight tools for my own workflow and put them on Site Tools Box (a directory of tools with absolutely no sign-up required).&lt;/p&gt;

&lt;p&gt;For checking a single page's assets (CSS, JS, images), I use their Dead Link Checker. (Link: &lt;a href="https://sitetoolsbox.com/tool.php?slug=http_status" rel="noopener noreferrer"&gt;https://sitetoolsbox.com/tool.php?slug=http_status&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;For checking a batch of URLs at once (up to 20 URLs), I use their Bulk HTTP Checker. (Link: &lt;a href="https://sitetoolsbox.com/tool.php?slug=http_status_batch" rel="noopener noreferrer"&gt;https://sitetoolsbox.com/tool.php?slug=http_status_batch&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Best Practices for Handling the Results&lt;br&gt;
Once you have a list of 404s, don't just delete the links blindly.&lt;/p&gt;

&lt;p&gt;If the page was deleted: Set up a 301 Redirect to the closest relevant page. This preserves your SEO juice.&lt;/p&gt;

&lt;p&gt;If the page is temporarily down (500/502): Don't touch it yet. Wait a day and check again. It might just be a server hiccup.&lt;/p&gt;

&lt;p&gt;If the external site is permanently dead: Remove the link and replace it with plain text, or find an alternative source.&lt;/p&gt;

&lt;p&gt;Don't let broken links sit on your site. Write a script, run a weekly check, and keep your site's SEO healthy.&lt;/p&gt;

&lt;p&gt;How do you handle broken links in your workflow? Do you use a CLI tool or a browser extension? Let me know in the comments below! 💬&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>seo</category>
      <category>productivity</category>
      <category>nocode</category>
    </item>
    <item>
      <title>Stop Guessing: A Developer's Guide to Demystifying HTTP Status Codes</title>
      <dc:creator>laing lii</dc:creator>
      <pubDate>Tue, 20 Oct 2026 00:57:14 +0000</pubDate>
      <link>https://dev.to/laing_lii_8c1214ffb0b60ec/stop-guessing-a-developers-guide-to-demystifying-http-status-codes-5dg1</link>
      <guid>https://dev.to/laing_lii_8c1214ffb0b60ec/stop-guessing-a-developers-guide-to-demystifying-http-status-codes-5dg1</guid>
      <description>&lt;ol&gt;
&lt;li&gt;The 2xx Family (Success)
These are the ones we like.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;200 OK: The standard response for a successful HTTP request. The server did its job.&lt;/p&gt;

&lt;p&gt;201 Created: Usually returned after a successful POST request (like creating a new user or posting a new article). The resource was successfully created.&lt;/p&gt;

&lt;p&gt;If you are seeing these, your API is working perfectly. Go grab a coffee. ☕&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The 3xx Family (Redirection)
This is where SEO and infrastructure issues usually begin.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;301 Moved Permanently: The resource has been permanently moved to a new URL. Pro Tip: Always use 301s when migrating websites to preserve your Google SEO ranking.&lt;/p&gt;

&lt;p&gt;302 Found (Temporary Redirect): The resource is temporarily at a different URL. Don't use this for permanent moves, or search engines will get confused.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The 4xx Family (Client-Side Errors)
This means the client (the browser or the developer) messed up.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;400 Bad Request: The server cannot process the request due to a client error (e.g., malformed request syntax, invalid JSON).&lt;/p&gt;

&lt;p&gt;401 Unauthorized: You are not authenticated. You haven't logged in, or your API token is missing/invalid.&lt;/p&gt;

&lt;p&gt;403 Forbidden: You are authenticated, but you don't have permission to access this resource. (e.g., a normal user trying to access an admin panel).&lt;/p&gt;

&lt;p&gt;404 Not Found: The classic. The server can't find the requested resource. It's either deleted or the URL is wrong.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The 5xx Family (Server-Side Errors)
The server failed to fulfill a valid request. This is where backend developers start sweating.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;500 Internal Server Error: The catch-all error. It means the server encountered an unexpected condition. You need to check your backend logs immediately.&lt;/p&gt;

&lt;p&gt;502 Bad Gateway: Your reverse proxy (Nginx/Apache) tried to talk to your backend service (PHP-FPM, Node.js), but the backend gave an invalid response. Usually caused by the backend crashing or timing out.&lt;/p&gt;

&lt;p&gt;504 Gateway Timeout: Similar to 502, but the backend simply took too long to respond. Your server might be overwhelmed or the script is running an infinite loop.&lt;/p&gt;

&lt;p&gt;🛠️ How to Debug Status Codes Quickly (Without Terminal)&lt;br&gt;
When you are building an API or migrating a server, your browser's developer tools are great. But what if you just want to check if a specific URL is returning the right status code right now without opening Postman or writing a cURL command?&lt;/p&gt;

&lt;p&gt;I used to open my terminal, type curl -I &lt;a href="https://example.com" rel="noopener noreferrer"&gt;https://example.com&lt;/a&gt;, and read the headers. It works, but it breaks my flow.&lt;/p&gt;

&lt;p&gt;To speed this up, I recently started using a lightweight web toolset called Site Tools Box.&lt;/p&gt;

&lt;p&gt;They have a free HTTP Status Checker that does exactly one thing, and does it well:&lt;/p&gt;

&lt;p&gt;You paste the URL.&lt;/p&gt;

&lt;p&gt;It instantly returns the Status Code, Response Headers, and Response Time.&lt;/p&gt;

&lt;p&gt;(No, you don't need to sign up, and it doesn't throw 50 ads in your face.)&lt;/p&gt;

&lt;p&gt;It’s incredibly useful when I need to quickly verify:&lt;/p&gt;

&lt;p&gt;If my 301 redirects are properly configured.&lt;/p&gt;

&lt;p&gt;If a website is actually down (is it a 502 or a 504?).&lt;/p&gt;

&lt;p&gt;If an API endpoint requires auth (it will return a 401 immediately).&lt;/p&gt;

&lt;p&gt;Wrap Up&lt;br&gt;
Never underestimate the power of a status code. It is the fastest way to tell if the problem is in your frontend code, your network configuration, or your backend server.&lt;/p&gt;

&lt;p&gt;Next time you get a 502, don't just restart the server blindly. Check the status code, read the headers, and use the right tools to isolate the issue.&lt;/p&gt;

&lt;p&gt;Happy debugging! 🚀&lt;/p&gt;

</description>
      <category>http</category>
    </item>
  </channel>
</rss>
