<?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: Rohit Roy</title>
    <description>The latest articles on DEV Community by Rohit Roy (@rohitroy11).</description>
    <link>https://dev.to/rohitroy11</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%2F3993980%2F6a527d41-c4c3-4697-9d71-c848a764f947.jpg</url>
      <title>DEV Community: Rohit Roy</title>
      <link>https://dev.to/rohitroy11</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rohitroy11"/>
    <language>en</language>
    <item>
      <title>I tested 12 job search tools. they all failed the same way.</title>
      <dc:creator>Rohit Roy</dc:creator>
      <pubDate>Sat, 20 Jun 2026 11:14:42 +0000</pubDate>
      <link>https://dev.to/rohitroy11/i-tested-12-job-search-tools-they-all-failed-the-same-way-1bbb</link>
      <guid>https://dev.to/rohitroy11/i-tested-12-job-search-tools-they-all-failed-the-same-way-1bbb</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;took me a week to write this. not ai-generated, not a listicle. just something i genuinely wanted to exist. hope it's worth your time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The third time I opened the same Greenhouse posting in one week - same role, same company, reposted by a different aggregator each time. I closed the tab and opened a spreadsheet instead. Not because I'd found a better tool. Because I'd run out of tools to try.&lt;/p&gt;

&lt;p&gt;By that point I'd cycled through twelve different ways of finding a job. Some were apps, some were threads, one was a Chrome extension, one was a literal sheet of rows and columns. And underneath all twelve, the same failure kept showing up in a different costume. This is the story of what that failure actually was, and the pipeline I ended up building once I got tired enough of it to treat my own job search like an engineering problem instead of a chore.&lt;/p&gt;

&lt;p&gt;If you just want the code: it's called &lt;a href="https://github.com/kayden-vs/jobradar" rel="noopener noreferrer"&gt;JobRadar&lt;/a&gt;, it's open source, and it runs entirely on free-tier APIs. Here's how it got built.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Twelve
&lt;/h2&gt;

&lt;p&gt;In no particular order, because none of them particularly won:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;LinkedIn job alerts&lt;/strong&gt; - technically real-time. Practically, by the time the email landed, forty recruiters had already reposted the same role and the original posting had three hundred applicants.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Indeed&lt;/strong&gt; - a great tool if your job search also doubles as an archaeology project. Half the listings predate the current presidential administration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Naukri.com&lt;/strong&gt; - enormous volume. A single keyword and location search returns hundreds of cards. The problem is that "Actively hiring" apparently means "was actively hiring, at some point, possibly last quarter."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Wellfound (AngelList)&lt;/strong&gt; - clean UI, genuinely good startup listings, and a bot-detection system aggressive enough to rate-limit a human for refreshing too often. Ironic, in hindsight, given what I eventually built.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hacker News's monthly "Who is Hiring?" thread&lt;/strong&gt; - the best signal-to-noise ratio of anything on this list, and also the worst UX. No notifications, no filtering, just Ctrl+F against a thousand-comment page once a month and hope you didn't miss the window.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Eight different "fresher jobs" blogs, via RSS&lt;/strong&gt; - individually useful. Collectively, a second job whose only task was reading my own RSS reader.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A couple of Telegram "job alert" channels run by strangers&lt;/strong&gt; - no visibility into what they were filtering on, if anything. A firehose with a Telegram skin.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A paid "AI-matched" job platform&lt;/strong&gt; - gave every listing a match score. Wouldn't tell me &lt;em&gt;why&lt;/em&gt; without upgrading to a higher tier. A black box with a paywall bolted on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A browser extension that auto-fills and auto-submits applications&lt;/strong&gt; - applied me, automatically, to a role explicitly requiring "5+ years of distributed systems experience" off a search filtered for entry-level roles. It doesn't read. It clicks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Google Alerts for "hiring backend intern"&lt;/strong&gt; - mostly surfaced the same five SEO-farmed aggregator sites reposting each other's content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Job-posting accounts on X/Twitter&lt;/strong&gt; - great in the moment, scrolling. Completely unsearchable five minutes later.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A spreadsheet&lt;/strong&gt; - the oldest job-search tool there is, and the one that finally told me the truth: I was the deduplication layer. I was the filter. Every other tool had just been generating more raw material for me to filter by hand.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The mistake all twelve made
&lt;/h2&gt;

&lt;p&gt;Here's the pattern, once you put all twelve side by side: every single one of them optimized for &lt;em&gt;more&lt;/em&gt;. More listings, more alerts, more "matches," more reach. Not one of them optimized for &lt;em&gt;fewer, better&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That's a reasonable thing for a job board to optimize for more listings in front of more eyeballs is the business model. But it's the wrong thing for a job &lt;em&gt;seeker&lt;/em&gt; to optimize for. There are, conservatively, several thousand live tech postings on any given day across the sources I cared about. The actual bottleneck in a job search has never been &lt;em&gt;discovery&lt;/em&gt;. It's &lt;em&gt;filtering&lt;/em&gt;, getting from "thousands of postings exist" down to "here are the four that are actually worth fifteen minutes of a tailored cover note," and then doing that again tomorrow, and the day after.&lt;/p&gt;

&lt;p&gt;None of the twelve did that part. They all handed me a bigger pile and called it help.&lt;/p&gt;

&lt;p&gt;I'm a backend engineer. Filtering a large, noisy stream down to a small, relevant one is not a novel problem, it's a pipeline. I had no good reason to be running that pipeline manually, by hand, on my own future, every single morning.&lt;/p&gt;

&lt;h2&gt;
  
  
  So I built the filter instead of using a search engine
&lt;/h2&gt;

&lt;p&gt;JobRadar is the result. It's not a job board, and it's not a smarter way to search — it's an automated funnel that runs twice a day and does, mechanically, exactly what I'd been doing by hand for two months.&lt;/p&gt;

&lt;p&gt;A full run takes 17–20 minutes, end to end, and fires twice a day on a cron job. Most of that time is the scraping stage, not the AI - the actual filtering is the fast part. Let me walk through why each layer exists, because the order matters as much as the steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  15 sources, because no single source tells the truth
&lt;/h3&gt;

&lt;p&gt;The "more listings" instinct from those twelve tools wasn't entirely wrong — it's just that volume needs to come &lt;em&gt;before&lt;/em&gt; the filtering, not instead of it. JobRadar pulls from nine ATS platforms directly through their structured APIs (Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Rippling, BambooHR, Recruitee, Personio — no scraping, no headless browser, just polling the same JSON endpoints the company's own careers page calls), plus Naukri, Internshala, Hirist, the YC jobs board, eight-plus fresher-jobs blogs via concurrent RSS, the HN hiring thread (auto-discovered via Algolia, so it never needs a manual thread-ID update), Reddit job feeds, RemoteOK/Jobicy, hiring.cafe's internal API, and a tiered set of Google-dork queries through Serper.dev for the career pages and hidden application forms that none of the structured sources ever surface.&lt;/p&gt;

&lt;p&gt;That's roughly 8,500 raw job objects on a typical run. Almost none of them get seen by a human. That's the point.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deduplication: the part every other tool quietly outsourced to me
&lt;/h3&gt;

&lt;p&gt;The same Greenhouse posting showing up via the ATS poll &lt;em&gt;and&lt;/em&gt; via hiring.cafe &lt;em&gt;and&lt;/em&gt; via a Google dork result is the default state of this data, not an edge case. JobRadar runs two hashes against every job, a normalized Title+Company+Location MD5 (collapsing "Pvt Ltd" vs "Private Limited," city aliases like Bengaluru vs Bangalore, and stray year noise in titles) and a canonical-URL MD5 with tracking parameters stripped. One check catches duplicate listings; the other catches the same listing reposted from a different domain. Both are checked against an in-memory set for the current run and a persistent SQLite store across all previous runs, so a job I've already seen and already dismissed - never resurfaces. That single layer is most of what those eight RSS feeds and three job boards were silently asking me to do by hand.&lt;/p&gt;

&lt;h3&gt;
  
  
  A rule-based prefilter that kills 90–95% of the pile, for free
&lt;/h3&gt;

&lt;p&gt;This is the layer that does the most damage to the noise, and it costs nothing: no network calls, no AI tokens, just plain Python running against each job's metadata: an age filter (default 45 days, parsing ISO dates, RFC dates, relative strings like "3 days ago," and Unix epochs), expiry-language detection ("application closed," "position filled"), a location filter that rejects rigid US/UK/EU-only roles outright, an experience-keyword scan that rejects "2+ years" or "senior engineer" language before it ever reaches an LLM, and configurable company/role blacklists. By the time this stage is done, ~8,000 jobs have become 100–150.&lt;/p&gt;

&lt;h3&gt;
  
  
  A ranker that learns what "relevant" means from a config file, not from code
&lt;/h3&gt;

&lt;p&gt;Before any of those 100–150 survivors get an expensive AI call, a heuristic ranker scores each one in pure Python. primary skill in the title, secondary skills, domain match, fresher-friendly signals, recency and queues the strongest matches first. The interesting part isn't the scoring logic itself; it's that every pattern it checks against is compiled dynamically from a YAML profile at runtime. Change your skills or target industries in that file, and the ranker's detection patterns rebuild themselves on the next run. No code change, no redeploy.&lt;/p&gt;

&lt;h3&gt;
  
  
  The AI layer, and why it doesn't just hand back a number
&lt;/h3&gt;

&lt;p&gt;This is where JobRadar differs most from tool #8 on that list above, the paid black-box scorer. Every surviving job gets sent to Llama 4 Scout on Groq's free tier, an MoE model that punches noticeably above its weight class for a free-tier option and scored 1–10 against a few-shot-calibrated rubric (two fixed anchor examples, a 9 and a 3, so the scale doesn't quietly drift across hundreds of runs the way unconstrained LLM scoring tends to). Jobs scoring below 6 come back with empty reasoning fields by design, there's no value in spending tokens explaining why a bad match is bad, so that single rule cuts response tokens by roughly 90% on the low-relevance majority. Jobs scoring 8 or above get one extra field: &lt;code&gt;apply_angle&lt;/code&gt;, a single actionable sentence on what to actually lead with in the cover note for that specific role. The scoring isn't a vibe. It's a number with a reason attached, every time it matters.&lt;/p&gt;

&lt;p&gt;A 5-second throttle between requests keeps the whole run at roughly 28,800 tokens per minute, just under Groq's 30K free-tier ceiling and a 200K-token budget per run keeps two runs a day comfortably inside the 500K daily limit. None of this requires a paid plan. It requires knowing where the free tier's actual edges are and staying a few percent inside them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Delivery: a push notification, not a dashboard I have to remember to open
&lt;/h3&gt;

&lt;p&gt;Score 8–10 fires an instant Telegram push - reason, highlights, red flags, apply angle, all in the message. Score 6–7 lands in a twice-daily digest card instead of interrupting me. Score 5 gets logged to SQLite but never surfaces. Below 5, it's gone, and I never know it existed. Out of ~8,500 jobs scraped on a typical run, somewhere between two and six actually reach me as something worth acting on. That ratio - thousands in, single digits out is the entire value proposition. Every tool on the list of twelve had that ratio backwards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running on free tiers wasn't a constraint. It was a design goal.
&lt;/h2&gt;

&lt;p&gt;I didn't build JobRadar with a budget in mind so much as a refusal to have one. Groq's free tier, Serper's free 2,500 queries a month (JobRadar uses about 25 per run, comfortably inside that), and Telegram's bot API (free, unlimited, always has been) cover the entire stack. There's no point in the pipeline where money changes hands. That matters more than it sounds like it should, for a tool aimed at the exact audience least able to justify a $12/month subscription for something that's supposed to be helping them get &lt;em&gt;paid&lt;/em&gt;, not spending more of the money they don't have yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's not actually about me
&lt;/h2&gt;

&lt;p&gt;I built this for a backend/Go internship search based out of India, and that bias shows up in the source mix - Naukri, Internshala, and the fresher blogs are not exactly global infrastructure. But every signal the pipeline acts on - skills, target roles, locations, acceptable vs. hard-reject geographies, industries, even the numeric weights in the ranker, lives in one &lt;code&gt;profile.yaml&lt;/code&gt; file, not in the code. A cybersecurity candidate, a data engineer, or a mobile developer can repoint the entire pipeline at their own search by editing that one file. The prefilter, the ranker, and the AI scorer all rebuild their pattern-matching from whatever's in there, on every run, automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it, or take it apart
&lt;/h2&gt;

&lt;p&gt;If you're a fresher drowning in the same noise, maybe it saves you some evenings. JobRadar is MIT licensed and entirely open: &lt;a href="https://github.com/kayden-vs/jobradar" rel="noopener noreferrer"&gt;&lt;strong&gt;github.com/kayden-vs/jobradar&lt;/strong&gt;&lt;/a&gt;. The setup guide walks through API keys, the full &lt;code&gt;profile.yaml&lt;/code&gt; field reference, and how to tune the ranker weights without touching code. If you're in the middle of a job search and recognize even three of those twelve tools from the list above, it might save you the few hours a week I was spending being my own deduplication layer.&lt;/p&gt;

&lt;p&gt;And if you're a developer rather than a job seeker right now, the most useful contribution isn't a bug fix, it's a new source. There's a &lt;code&gt;Job&lt;/code&gt; dataclass contract and a contributing guide that walks through wiring one in. I haven't opened a duplicate Greenhouse tab since I shipped this, and I'd like that to be true for more people than just me.&lt;/p&gt;

&lt;p&gt;And if you're a recruiter reading this - yes, I'm available for backend roles. Preferably ones that actually accept freshers.&lt;/p&gt;

</description>
      <category>career</category>
      <category>opensou</category>
      <category>python</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
