<?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: Mr Zack</title>
    <description>The latest articles on DEV Community by Mr Zack (@tactful_anvil).</description>
    <link>https://dev.to/tactful_anvil</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%2F4073833%2F554e6257-7bf5-41c3-a0e1-15f1d0e45abe.png</url>
      <title>DEV Community: Mr Zack</title>
      <link>https://dev.to/tactful_anvil</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tactful_anvil"/>
    <language>en</language>
    <item>
      <title>Kalshi's API is flooded with 8,000+ zero-volume parlay markets. If your scraper reads /markets, it's been empty since Sept 4.</title>
      <dc:creator>Mr Zack</dc:creator>
      <pubDate>Fri, 04 Sep 2026 19:46:50 +0000</pubDate>
      <link>https://dev.to/tactful_anvil/kalshis-api-is-flooded-with-8000-zero-volume-parlay-markets-if-your-scraper-reads-markets-b3</link>
      <guid>https://dev.to/tactful_anvil/kalshis-api-is-flooded-with-8000-zero-volume-parlay-markets-if-your-scraper-reads-markets-b3</guid>
      <description>&lt;p&gt;Yesterday one of my Apify Actors — a cross-platform "biggest movers" feed for Polymarket and Kalshi — ran, succeeded, and delivered 100 rows. Every single row was Polymarket. The Kalshi half of the product had silently gone to zero, and nothing in the run status said so.&lt;/p&gt;

&lt;p&gt;Here's what happened, how I caught it, and the one query parameter that fixes it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed on Kalshi
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;GET https://api.elections.kalshi.com/trade-api/v2/markets?status=open&amp;amp;limit=1000&lt;/code&gt; used to return a sensible mix of open markets. Since &lt;strong&gt;September 4, 2026&lt;/strong&gt; the first pages look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;page 1: 1000 markets, 1000 multivariate, 0 with 24h volume
page 2: 1000 markets, 1000 multivariate, 0 with 24h volume
...
page 8: 1000 markets, 1000 multivariate, 0 with 24h volume
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;8,000 markets in a row, all with a ticker like &lt;code&gt;KXMVECROSSCATEGORY-SHARD1-S2026…-FE61…&lt;/code&gt;, a &lt;code&gt;mve_collection_ticker&lt;/code&gt; field, a 26-leg &lt;code&gt;mve_selected_legs&lt;/code&gt; array (26 college-football moneylines chained together), &lt;code&gt;volume_24h_fp: "0.00"&lt;/code&gt; and &lt;code&gt;last_price_dollars: "0.0000"&lt;/code&gt;. They are auto-generated multivariate ("parlay") combinations. They're valid markets, they're just not something anyone is trading, and there are thousands of them created every day.&lt;/p&gt;

&lt;p&gt;My Actor's Kalshi loop scanned "up to 4× the requested market count" — 800 markets — and stopped. All 800 were parlay shards. Zero Kalshi rows. The Polymarket leg still worked, so the dataset was non-empty, so the run was &lt;code&gt;SUCCEEDED&lt;/code&gt;. This is the failure mode I'm most afraid of: &lt;strong&gt;success-rate stays 100% while the output quietly loses half its value.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I caught it
&lt;/h2&gt;

&lt;p&gt;Not from the run status. I run a free local canary for every Actor before I look at the cloud: the production parser hit the live source from my own machine, with gates on &lt;em&gt;counts and field coverage&lt;/em&gt;, not just exit codes. Yesterday's gate for this Actor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;PASS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;polymarket&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;markets&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;FAIL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;kalshi&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;markets&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;w/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="err"&gt;h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;vol&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;scanned&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;PASS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;filters&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;FAIL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;both&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;platforms&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;top&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"polymarket"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;100&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;Two red lines. If I had only checked "did it succeed / did it return 100 rows", I'd have seen nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix: &lt;code&gt;mve_filter=exclude&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Kalshi's API has an (under-documented) filter for exactly this:&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 /trade-api/v2/markets?status=open&amp;amp;limit=1000&amp;amp;mve_filter=exclude
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With it, page 1 goes from 0 to 45 markets with 24-hour volume, and by page 4 you have ~600 real, actively traded markets. Ten pages (10k markets) give &lt;strong&gt;2,588 open Kalshi markets with non-zero 24h volume&lt;/strong&gt; — that's the real universe.&lt;/p&gt;

&lt;p&gt;I also made two defensive changes so this can't recur silently:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Skip anything with &lt;code&gt;mve_collection_ticker&lt;/code&gt; or &lt;code&gt;mve_selected_legs&lt;/code&gt; in the normalizer&lt;/strong&gt;, regardless of what the API returns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paginate by "useful markets collected", not "raw markets scanned"&lt;/strong&gt; — keep pulling pages (cap 10) until I have at least 2× the requested top-N with volume &amp;gt; 0.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After the fix, the same default run returns 51 Polymarket + 49 Kalshi movers in the top 100, and the Kalshi log line says &lt;code&gt;618 markets with 24h volume fetched&lt;/code&gt; instead of nothing.&lt;/p&gt;

&lt;p&gt;Note the &lt;code&gt;/events?with_nested_markets=true&lt;/code&gt; endpoint is &lt;em&gt;not&lt;/em&gt; flooded (0 MVE events on page 1), so if you're already on events you're fine. It's specifically &lt;code&gt;/markets&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you scrape Kalshi, check your last few days
&lt;/h2&gt;

&lt;p&gt;Any pipeline built on &lt;code&gt;/markets?status=open&lt;/code&gt; that either (a) stops after N pages or (b) filters on &lt;code&gt;volume_24h &amp;gt; 0&lt;/code&gt; after fetching, has most likely been returning a near-empty Kalshi set since Sept 4. Symptoms: dashboards with only Polymarket, arbitrage scanners with zero Kalshi pairs, "market count" charts falling off a cliff. Add &lt;code&gt;mve_filter=exclude&lt;/code&gt; and re-run.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Actor
&lt;/h2&gt;

&lt;p&gt;The fixed feed is live: &lt;strong&gt;&lt;a href="https://apify.com/tactful_anvil/prediction-market-movers" rel="noopener noreferrer"&gt;Prediction Market Movers | Polymarket &amp;amp; Kalshi Catalyst Feed&lt;/a&gt;&lt;/strong&gt; — one ranked list of the biggest 24h odds swings, volume spikes and closing-soon markets across both platforms, each with a 0–100 catalyst score and signals like &lt;code&gt;BIG_SWING&lt;/code&gt;, &lt;code&gt;VOLUME_SPIKE&lt;/code&gt;, &lt;code&gt;CLOSING_SOON&lt;/code&gt;, &lt;code&gt;FAST_MOVER_1H&lt;/code&gt;. HTTP-only, public APIs, no keys; you pay per ranked row (~$0.01), and a default run costs about a cent. It also works as an MCP tool if you want an agent to ask "what moved on prediction markets today?"&lt;/p&gt;

&lt;p&gt;Sibling Actors if you want the rest of the stack: &lt;a href="https://apify.com/tactful_anvil/polymarket-kalshi-arbitrage-scanner" rel="noopener noreferrer"&gt;Polymarket ↔ Kalshi Arbitrage Scanner&lt;/a&gt;, &lt;a href="https://apify.com/tactful_anvil/polymarket-top-traders-scraper" rel="noopener noreferrer"&gt;Polymarket Top Traders&lt;/a&gt;, &lt;a href="https://apify.com/tactful_anvil/kalshi-weather-markets-scraper" rel="noopener noreferrer"&gt;Kalshi Weather Markets&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If this saved you a debugging session, a ⭐ or bookmark on the Actor page helps a lot — and if you've seen other Kalshi API changes this week, tell me in the comments so I can add gates for them.&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>api</category>
      <category>node</category>
      <category>datascience</category>
    </item>
    <item>
      <title>I pulled the open positions of Polymarket's 25 most profitable traders. $7.5M is sitting in just 5 bets.</title>
      <dc:creator>Mr Zack</dc:creator>
      <pubDate>Thu, 03 Sep 2026 19:33:06 +0000</pubDate>
      <link>https://dev.to/tactful_anvil/i-pulled-the-open-positions-of-polymarkets-25-most-profitable-traders-75m-is-sitting-in-just-5-j8o</link>
      <guid>https://dev.to/tactful_anvil/i-pulled-the-open-positions-of-polymarkets-25-most-profitable-traders-75m-is-sitting-in-just-5-j8o</guid>
      <description>&lt;p&gt;Polymarket publishes a leaderboard. It also publishes every wallet's positions. Nobody joins the two, so I did — with a scraper that hits the public &lt;code&gt;data-api&lt;/code&gt; (no login, no key) and writes one flat row per whale position.&lt;/p&gt;

&lt;p&gt;Here is what the top 25 traders by 30-day PnL were holding this morning (September 4, 2026).&lt;/p&gt;

&lt;h2&gt;
  
  
  The headline numbers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;25 traders, $2.03M combined 30-day profit.&lt;/strong&gt; Median $61.5k. #1 (Sassy-Bucket) made $206k on only $203k of volume — a ~100% return; #3 (BrotherObama) needed $548k of volume for $176k.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;318 open positions worth $7.53M&lt;/strong&gt;, sitting on &lt;strong&gt;$980k of unrealized profit&lt;/strong&gt;. 188 of 318 (59%) are currently green.&lt;/li&gt;
&lt;li&gt;Average entry price 0.55, average current price 0.60. They buy at coin-flip odds and hold while the market drifts their way.&lt;/li&gt;
&lt;li&gt;Median time to resolution: &lt;strong&gt;60 days&lt;/strong&gt;. Only 28% of positions resolve within a week. These are not scalpers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where the money actually is
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Positions&lt;/th&gt;
&lt;th&gt;Current value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Crypto price levels ("Will BTC dip to $X by Dec 31?")&lt;/td&gt;
&lt;td&gt;69&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$4.50M&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Macro (Fed rate decisions)&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;$1.11M&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sports (MLB O/U, US Open tennis)&lt;/td&gt;
&lt;td&gt;44&lt;/td&gt;
&lt;td&gt;$0.52M&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Politics / legislation&lt;/td&gt;
&lt;td&gt;41&lt;/td&gt;
&lt;td&gt;$0.17M&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Everything else&lt;/td&gt;
&lt;td&gt;148&lt;/td&gt;
&lt;td&gt;$1.24M&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One wallet (JnStrtPrdctnMrkts) owns the five largest positions on the board — all of them &lt;strong&gt;"No" on Bitcoin/Ethereum dip markets&lt;/strong&gt;: "ETH dips to $1,500 by Dec 31" No at $865k (entered 0.62, now 0.86, +$242k), "BTC dips to $55k" No at $589k (+$209k), "$50k" No at $552k, "$45k" No at $391k, "ETH $1,250" No at $370k. That is a $2.8M ladder betting that crypto simply does not crash this year, bought when the market priced the crash at 25–45%.&lt;/p&gt;

&lt;h2&gt;
  
  
  The most crowded trades
&lt;/h2&gt;

&lt;p&gt;Markets where several whales independently hold the same side are the closest thing to a consensus signal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"No change in Fed rates after the September 2026 meeting" — 5 of 25 whales, all Yes, $749k.&lt;/strong&gt; Plus 3 whales on "No" to a 25 bps hike ($309k). The smart-money book is unanimous: nothing happens in September.&lt;/li&gt;
&lt;li&gt;"Clarity Act (H.R.3633) signed into law in 2026?" — 3 whales, all Yes, $108k.&lt;/li&gt;
&lt;li&gt;Sports are where they disagree: Giants–Pirates O/U 8.5 has 2 whales Over and 2 Under. Struff–Cerundolo at the US Open: 3 on Cerundolo, 2 on Struff. Sports positions are small ($5–30k) and short-dated — this looks like edge-hunting, not conviction.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What this is useful for
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Copy-trading feeds&lt;/strong&gt;: schedule the scraper hourly, diff &lt;code&gt;conditionId + wallet&lt;/code&gt; against the previous run, and you get "whale opened / closed a position" alerts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sentiment on macro &amp;amp; crypto&lt;/strong&gt;: whale positioning on Fed and BTC-level markets moves before the retail price does; this is the cheapest way to watch it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Research&lt;/strong&gt;: the &lt;code&gt;avgPrice&lt;/code&gt; vs &lt;code&gt;curPrice&lt;/code&gt; columns give you each whale's entry, so you can measure who's early and who's chasing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How it's built
&lt;/h2&gt;

&lt;p&gt;Two public endpoints: &lt;code&gt;GET /v1/leaderboard?window=1m&amp;amp;rankType=pnl&amp;amp;limit=25&lt;/code&gt; for the roster and &lt;code&gt;GET /positions?user=&amp;lt;wallet&amp;gt;&amp;amp;limit=100&amp;amp;sortBy=CURRENT&lt;/code&gt; per wallet. Pure HTTP, ~25 requests, 10–20 seconds for the whole board. Output per row: rank, wallet, trader name, 30-day PnL and volume, market, side, shares, avg vs current price, current value, cash PnL, % PnL, end date, and a direct market URL. A watchlist mode accepts your own wallet list, and only position rows are charged.&lt;/p&gt;

&lt;p&gt;It runs on Apify as &lt;strong&gt;&lt;a href="https://apify.com/tactful_anvil/polymarket-top-traders-scraper" rel="noopener noreferrer"&gt;Polymarket Top Traders Scraper | Whale Positions &amp;amp; Copy Feed&lt;/a&gt;&lt;/strong&gt; — schedule it, pipe it to Sheets/Slack, or call it from an MCP client. Siblings if you want the full prediction-market stack: &lt;a href="https://apify.com/tactful_anvil/polymarket-kalshi-arbitrage-scanner" rel="noopener noreferrer"&gt;Polymarket Kalshi Arbitrage Scanner&lt;/a&gt; (same market, two venues, price gap) and &lt;a href="https://apify.com/tactful_anvil/prediction-market-movers" rel="noopener noreferrer"&gt;Prediction Market Movers&lt;/a&gt; (biggest 24h probability swings on both platforms).&lt;/p&gt;

&lt;p&gt;If you run it and it saves you a spreadsheet afternoon, a review or bookmark on the Apify page helps more than you'd think.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Not financial advice. Data is a snapshot; whales close positions too.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>datascience</category>
      <category>crypto</category>
      <category>api</category>
    </item>
    <item>
      <title>I scraped all 545 startups for sale on Microns. Sellers ask 4.3x revenue. Buyers pay 3.3x.</title>
      <dc:creator>Mr Zack</dc:creator>
      <pubDate>Wed, 02 Sep 2026 19:44:28 +0000</pubDate>
      <link>https://dev.to/tactful_anvil/i-scraped-all-545-startups-for-sale-on-microns-sellers-ask-43x-revenue-buyers-pay-33x-1a14</link>
      <guid>https://dev.to/tactful_anvil/i-scraped-all-545-startups-for-sale-on-microns-sellers-ask-43x-revenue-buyers-pay-33x-1a14</guid>
      <description>&lt;p&gt;Every micro-acquisition thread ends with the same question: &lt;em&gt;what multiple is fair for a tiny SaaS?&lt;/em&gt; People answer from memory. I'd rather answer from the board.&lt;/p&gt;

&lt;p&gt;So I pulled every listing on &lt;a href="https://www.microns.io" rel="noopener noreferrer"&gt;Microns&lt;/a&gt; — the marketplace where indie founders sell $1K–$100K micro-startups — as of September 3, 2026. That's &lt;strong&gt;545 listings: 390 still for sale, 155 marked sold.&lt;/strong&gt; Here's what the numbers say.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The ask/clear gap is a full turn of revenue
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Listings with revenue&lt;/th&gt;
&lt;th&gt;Median asking price&lt;/th&gt;
&lt;th&gt;Median price ÷ ARR&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Available&lt;/strong&gt; (for sale now)&lt;/td&gt;
&lt;td&gt;374&lt;/td&gt;
&lt;td&gt;$10,750&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.26x&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Sold&lt;/strong&gt; (market comps)&lt;/td&gt;
&lt;td&gt;136&lt;/td&gt;
&lt;td&gt;$3,000&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.33x&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Sellers &lt;em&gt;ask&lt;/em&gt; 4.3x annual revenue. What actually &lt;em&gt;clears&lt;/em&gt; is 3.3x. If you're buying, the sold column is your anchor, not the listing page. If you're selling, pricing at 5x+ mostly means you'll still be listed in four months — median time on board for available listings is &lt;strong&gt;110 days&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And it's not a few outliers dragging the ask up: &lt;strong&gt;181 of the 390 available listings (46%) are priced above 5x revenue.&lt;/strong&gt; Only 27 of 136 sold listings (20%) cleared at more than 10x, and those are the tiny-revenue cases where a $3K price on $200 ARR shows up as "15x".&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Multiples depend on category more than on the startup
&lt;/h2&gt;

&lt;p&gt;Median &lt;em&gt;sold&lt;/em&gt; multiple by category (categories with at least 5 sold comps):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Sold comps&lt;/th&gt;
&lt;th&gt;Median multiple that cleared&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Directory&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;6.75x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Micro-SaaS&lt;/td&gt;
&lt;td&gt;36&lt;/td&gt;
&lt;td&gt;5.33x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Newsletter&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;4.20x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web App&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;3.14x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mobile App&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;2.95x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E-commerce&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;2.08x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;YouTube channel&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;1.12x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two things surprised me. Directories clear at the &lt;em&gt;highest&lt;/em&gt; multiple — low maintenance, recurring, SEO-driven cash. And YouTube channels clear at barely 1x revenue: buyers price in the key-person risk. If you own a directory, you're sitting on a more sellable asset than you think.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Where the underpriced deals are hiding
&lt;/h2&gt;

&lt;p&gt;Of 390 available listings, &lt;strong&gt;137 are priced at ≤3x revenue and 79 at ≤2x.&lt;/strong&gt; Thirty listings were added in the last 7 days. The good ones move in days — the median sold listing had a $3,000 price, which is exactly the size an indie buyer can close on a weekend.&lt;/p&gt;

&lt;p&gt;The top of my deal score right now (fresh + fairly priced + real revenue + real customers):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Startup&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Asking&lt;/th&gt;
&lt;th&gt;ARR&lt;/th&gt;
&lt;th&gt;Multiple&lt;/th&gt;
&lt;th&gt;Days listed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fashion Online Store&lt;/td&gt;
&lt;td&gt;E-commerce&lt;/td&gt;
&lt;td&gt;$109,000&lt;/td&gt;
&lt;td&gt;$341,000&lt;/td&gt;
&lt;td&gt;0.32x&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI Image-to-Video Generator&lt;/td&gt;
&lt;td&gt;Web App&lt;/td&gt;
&lt;td&gt;$30,000&lt;/td&gt;
&lt;td&gt;$55,933&lt;/td&gt;
&lt;td&gt;0.54x&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Amazon FBA Decor Brand&lt;/td&gt;
&lt;td&gt;E-commerce&lt;/td&gt;
&lt;td&gt;$85,000&lt;/td&gt;
&lt;td&gt;$103,000&lt;/td&gt;
&lt;td&gt;0.83x&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Relaxation Gummies Store&lt;/td&gt;
&lt;td&gt;E-commerce&lt;/td&gt;
&lt;td&gt;$36,000&lt;/td&gt;
&lt;td&gt;$38,330&lt;/td&gt;
&lt;td&gt;0.94x&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gamified Fitness / RPG Workout&lt;/td&gt;
&lt;td&gt;Micro-SaaS&lt;/td&gt;
&lt;td&gt;$19,000&lt;/td&gt;
&lt;td&gt;$18,107&lt;/td&gt;
&lt;td&gt;1.05x&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;E-commerce dominates the top because revenue there is gross, not net — which is exactly why you need the seller's &lt;code&gt;expenses&lt;/code&gt; and &lt;code&gt;businessModel&lt;/code&gt; fields next to the multiple before you get excited. The dataset carries both.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I get this every morning
&lt;/h2&gt;

&lt;p&gt;I didn't do this by hand. It's an Apify Actor I maintain: &lt;strong&gt;&lt;a href="https://apify.com/tactful_anvil/microns-startup-listings-scraper" rel="noopener noreferrer"&gt;Microns Startup Listings Scraper&lt;/a&gt;&lt;/strong&gt;. One run = the whole board, HTTP-only (no browser, no login, no proxies), with these fields per listing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;askingPriceUsd&lt;/code&gt;, &lt;code&gt;arrUsd&lt;/code&gt;, and &lt;code&gt;revenueMultiple&lt;/code&gt; (null when ARR is 0 or unpublished — never a fake number)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;status&lt;/code&gt; = &lt;code&gt;available&lt;/code&gt; or &lt;code&gt;sold&lt;/code&gt;, so the sold rows double as comps&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;customers&lt;/code&gt;, &lt;code&gt;pricePerCustomer&lt;/code&gt;, &lt;code&gt;publishedDate&lt;/code&gt;, &lt;code&gt;daysListed&lt;/code&gt;, &lt;code&gt;foundedYear&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;the seller's own &lt;code&gt;businessModel&lt;/code&gt;, &lt;code&gt;expenses&lt;/code&gt;, &lt;code&gt;growthOpportunity&lt;/code&gt;, &lt;code&gt;reasonForSelling&lt;/code&gt;, &lt;code&gt;askingPriceReasoning&lt;/code&gt;, &lt;code&gt;techStack&lt;/code&gt;, &lt;code&gt;competitors&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dealScore&lt;/code&gt; 0–100: revenue evidence + price fairness vs ~3x + traction + freshness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every run also writes a &lt;code&gt;SUMMARY&lt;/code&gt; record with board totals, available vs sold, &lt;strong&gt;median revenue multiple&lt;/strong&gt; and new-this-week count — so a weekly &lt;code&gt;listingStatus: "sold"&lt;/code&gt; run gives you a live micro-startup valuation index that nobody publishes.&lt;/p&gt;

&lt;p&gt;The daily deal-alert input I use, on a schedule with a Slack integration:&lt;br&gt;
&lt;/p&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;"listingStatus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"available"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"minArrUsd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"maxRevenueMultiple"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"sortBy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dealScore"&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;Pay-per-result, so a filtered run like that costs cents. It's also callable from AI agents (MCP) — "find me SaaS listings under $20K priced below 3x revenue, added this week" is one tool call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats, because this is money
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Revenue on Microns is self-reported. Multiples are a screening tool, not diligence.&lt;/li&gt;
&lt;li&gt;"Sold" means the seller marked it sold; the clearing price is the &lt;em&gt;listed&lt;/em&gt; price at that time, which may differ from the final negotiated number.&lt;/li&gt;
&lt;li&gt;Sample sizes per category are small (7–36 comps). Treat category medians as direction, not law.&lt;/li&gt;
&lt;li&gt;Not financial advice. Verify on the listing page before you message a founder.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you buy, sell, or benchmark micro-startups and want a field added, open an Issue on the Actor page — the parser is monitored daily.&lt;/p&gt;

</description>
      <category>startup</category>
      <category>data</category>
      <category>webscraping</category>
      <category>indiehackers</category>
    </item>
    <item>
      <title>Finding risk-free arbitrage between Polymarket and Kalshi (and why most arb finders show you garbage)</title>
      <dc:creator>Mr Zack</dc:creator>
      <pubDate>Sat, 29 Aug 2026 19:40:21 +0000</pubDate>
      <link>https://dev.to/tactful_anvil/finding-risk-free-arbitrage-between-polymarket-and-kalshi-and-why-most-arb-finders-show-you-1o3e</link>
      <guid>https://dev.to/tactful_anvil/finding-risk-free-arbitrage-between-polymarket-and-kalshi-and-why-most-arb-finders-show-you-1o3e</guid>
      <description>&lt;p&gt;Prediction markets exploded this year. The same event — a Fed rate decision, an NFL game, tomorrow's NYC high temperature — often trades on &lt;strong&gt;both Polymarket and Kalshi at different prices&lt;/strong&gt;. Buy YES on one platform and NO on the other for a combined cost under $1.00 and you lock in profit no matter what happens. That's the theory.&lt;/p&gt;

&lt;p&gt;The practice: most cross-platform arb tools show you a wall of 90% "edges" that are actually &lt;strong&gt;mismatched markets&lt;/strong&gt;. "Fed rate &lt;em&gt;at&lt;/em&gt; 1.75%" paired with "Fed rate &lt;em&gt;above&lt;/em&gt; 2.75%". "Bank of England" paired with "Bank of Japan". "Will there be &lt;em&gt;no&lt;/em&gt; Gemini release" paired with "When will Gemini release". You waste an evening checking them one by one, find zero real arbs, and never open the tool again.&lt;/p&gt;

&lt;p&gt;I built a scanner that treats matching as the hard problem it is. Rules that killed the false positives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Numeric strikes must agree.&lt;/strong&gt; If both questions contain non-year numbers and they don't intersect, the pair is dead. 1.75 ≠ 2.75, ever.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Negation must agree.&lt;/strong&gt; "No X before 2027" never pairs with "X before 2027".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Directions must not conflict.&lt;/strong&gt; "Above" never pairs with "below"; "above" against no direction at all gets penalized — different payoff shapes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dates must be close.&lt;/strong&gt; End dates more than 3 days apart = different markets, even with identical wording.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edges above 15% are flagged suspicious, not celebrated.&lt;/strong&gt; A real cross-platform gap is 0.3–6%. If a tool shows you 90%, it matched the wrong market.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kalshi's 7% fee is subtracted&lt;/strong&gt; before anything is called an arb. A 1.5% gross gap that dies after fees is not an opportunity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On a full scan this morning — ~2,000 high-volume Polymarket binaries against ~60,000 open Kalshi markets — it matched 345 equivalent pairs and 25 of them were genuine net-positive arbs (0.3% to 6% after fees): Trump–Kim meeting, measles case counts, a couple of 2028 nominee long shots.&lt;/p&gt;

&lt;p&gt;Both APIs are public and unauthenticated (Polymarket's Gamma API, Kalshi's trade API v2), so the whole thing is plain HTTP — no proxies, no keys, no headless browser. The matcher is ~200 lines of deterministic token/entity logic: alias table (BTC→bitcoin, Fed→federal-reserve), day-of-month detection so "Dec 31" doesn't become a strike price, inverted-index blocking so 2k × 60k comparisons stay under 200ms.&lt;/p&gt;

&lt;p&gt;I packaged it as a pay-per-event Apify actor: &lt;a href="https://apify.com/tactful_anvil/polymarket-kalshi-arbitrage-scanner" rel="noopener noreferrer"&gt;Polymarket Kalshi Arbitrage Scanner&lt;/a&gt;. Run it on a 15–60 min schedule with &lt;code&gt;minNetEdgePct: 0&lt;/code&gt; and you only pay for rows that are actually actionable. If you trade weather markets specifically, the &lt;a href="https://apify.com/tactful_anvil/kalshi-weather-markets-scraper" rel="noopener noreferrer"&gt;Kalshi Weather Markets Scraper&lt;/a&gt; is the companion piece.&lt;/p&gt;

&lt;p&gt;Not financial advice — arbs decay in minutes, liquidity at the quoted ask matters, and you should always verify on-platform before putting money down. But if you're going to hunt cross-platform edges, at least hunt real ones.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>finance</category>
      <category>webscraping</category>
    </item>
    <item>
      <title>Stop Opening Two Ad Libraries Every Morning — One Feed for Google + LinkedIn Ads</title>
      <dc:creator>Mr Zack</dc:creator>
      <pubDate>Fri, 28 Aug 2026 19:09:17 +0000</pubDate>
      <link>https://dev.to/tactful_anvil/stop-opening-two-ad-libraries-every-morning-one-feed-for-google-linkedin-ads-6gj</link>
      <guid>https://dev.to/tactful_anvil/stop-opening-two-ad-libraries-every-morning-one-feed-for-google-linkedin-ads-6gj</guid>
      <description>&lt;p&gt;If you do competitive ad research, your morning probably looks like this: open the Google Ads Transparency Center, search the brand, screenshot a few creatives... then open the LinkedIn Ad Library, search the same brand again, and try to line the two up in a spreadsheet.&lt;/p&gt;

&lt;p&gt;Two tabs. Two search UIs. Two export formats (actually zero export formats — neither site has one).&lt;/p&gt;

&lt;p&gt;I built an Apify actor that collapses this into a single normalized feed: &lt;a href="https://apify.com/tactful_anvil/brand-ads-cross-network-spy" rel="noopener noreferrer"&gt;Brand Ads Spy — Google + LinkedIn Ads in One Feed&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Give it a list of brand names or domains. It pulls, for each brand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google Ads Transparency Center&lt;/strong&gt; — every active creative (text, image, video), regions, first/last shown dates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LinkedIn Ad Library&lt;/strong&gt; — every ad, advertiser, format, paying entity, EU run dates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...and returns them in one dataset with a shared schema:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;network&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;google&lt;/code&gt; or &lt;code&gt;linkedin&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;adId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;stable ID on that network&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;advertiser&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;advertiser / page name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;format&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text / image / video&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;adText&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;creative text where available&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;firstShownAt&lt;/code&gt; / &lt;code&gt;lastShownAt&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;date range the ad ran&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;isNew&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;first time this actor has seen this ad&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mediaUrls&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;creative assets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;libraryUrl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;deep link back to the source library&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;payer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;who paid (LinkedIn EU transparency data)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No login, no proxies, no browser rendering — both legs are plain HTTP, so runs finish in seconds and cost stays at &lt;strong&gt;$1.20 per 1,000 ad results&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitor mode: only pay for what's new
&lt;/h2&gt;

&lt;p&gt;Set &lt;code&gt;onlyNew: true&lt;/code&gt; and the actor remembers every ad ID it has seen (across both networks). The next run only emits — and only charges for — ads that appeared since last time. That turns it from a scraper into a change monitor: "tell me when my competitor launches a new campaign, on either network."&lt;/p&gt;

&lt;h2&gt;
  
  
  How to schedule it (the whole point)
&lt;/h2&gt;

&lt;p&gt;Ad intelligence is only useful if it's fresh. On Apify:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the actor page → &lt;strong&gt;Try for free&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Set your &lt;code&gt;brands&lt;/code&gt; list and &lt;code&gt;onlyNew: true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Save the task → &lt;strong&gt;Schedules&lt;/strong&gt; → e.g. &lt;code&gt;0 7 * * *&lt;/code&gt; (every morning, 7 AM)&lt;/li&gt;
&lt;li&gt;Add an integration (Slack, email, webhook) so new ads land where you work&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every morning you get a diff of your competitors' ad activity across Google and LinkedIn — without opening either library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why cross-network matters
&lt;/h2&gt;

&lt;p&gt;B2B brands stage campaigns differently per channel: LinkedIn gets the expensive lead-gen creative first, Google gets the retargeting variants a week later (or the reverse). Seeing one network gives you half the story; the interesting signal is in the &lt;em&gt;gap&lt;/em&gt; between them — a brand live on LinkedIn but dark on Google is usually mid-launch.&lt;/p&gt;

&lt;p&gt;If you only need the Google side, the standalone &lt;a href="https://apify.com/tactful_anvil/google-ads-transparency-scraper" rel="noopener noreferrer"&gt;Google Ads Transparency Scraper&lt;/a&gt; is $0.64/1k.&lt;/p&gt;

&lt;p&gt;Questions or feature requests — comments are open, and reviews on the actor page genuinely help a small builder. 🙏&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Your browser extensions can read every site you visit. Auditing 200 of them takes one scrape</title>
      <dc:creator>Mr Zack</dc:creator>
      <pubDate>Thu, 27 Aug 2026 19:10:47 +0000</pubDate>
      <link>https://dev.to/tactful_anvil/your-browser-extensions-can-read-every-site-you-visit-auditing-200-of-them-takes-one-scrape-3kho</link>
      <guid>https://dev.to/tactful_anvil/your-browser-extensions-can-read-every-site-you-visit-auditing-200-of-them-takes-one-scrape-3kho</guid>
      <description>&lt;p&gt;A Chrome extension with &lt;code&gt;&amp;lt;all_urls&amp;gt;&lt;/code&gt; host access can read your banking session, your email, your internal admin panels — every page you open. Most orgs have no idea which of the extensions their people installed request that level of access. The Chrome Web Store won't tell you in bulk: permission info lives inside each extension's manifest, one listing at a time.&lt;/p&gt;

&lt;p&gt;I kept seeing the same manual workflow: a security reviewer opens 40 extension pages, clicks through to the details, squints at the permission list, pastes findings into a sheet. Next quarter, repeat, because versions and permissions changed.&lt;/p&gt;

&lt;p&gt;That's a scraping problem, so I built &lt;a href="https://apify.com/tactful_anvil/chrome-web-store-intelligence-scraper" rel="noopener noreferrer"&gt;Chrome Web Store Intelligence &amp;amp; Permission-Risk Scraper&lt;/a&gt; — it turns any list of extensions, search queries, or whole categories into structured rows with a documented 0–100 permission-risk score. $2.40 per 1,000 extensions, HTTP-only, no login, no API key.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you get per extension
&lt;/h2&gt;

&lt;p&gt;One row per extension with the fields a review actually needs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;name&lt;/code&gt; / &lt;code&gt;extensionId&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;uBlock Origin&lt;/code&gt; / &lt;code&gt;cjpalhdl…&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;rating&lt;/code&gt; / &lt;code&gt;ratingCount&lt;/code&gt; / &lt;code&gt;userCount&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;4.7&lt;/code&gt; / &lt;code&gt;35450&lt;/code&gt; / &lt;code&gt;11000000&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;version&lt;/code&gt; / &lt;code&gt;lastUpdatedDays&lt;/code&gt; / &lt;code&gt;isAbandoned&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1.74.0&lt;/code&gt; / &lt;code&gt;0.3&lt;/code&gt; / &lt;code&gt;false&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;apiPermissions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;["scripting","tabs","cookies"]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hostPermissions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;["https://*/*"]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;permissionRiskScore&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;86&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;riskLevel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;critical&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;riskFlags&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;["broad_host_access","reads_cookies"]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The risk model is transparent: broad host access (&lt;code&gt;&amp;lt;all_urls&amp;gt;&lt;/code&gt;, &lt;code&gt;*://*/*&lt;/code&gt;), &lt;code&gt;debugger&lt;/code&gt;, &lt;code&gt;nativeMessaging&lt;/code&gt;, &lt;code&gt;proxy&lt;/code&gt;, &lt;code&gt;management&lt;/code&gt;, &lt;code&gt;cookies&lt;/code&gt;, &lt;code&gt;webRequest&lt;/code&gt;, &lt;code&gt;history&lt;/code&gt; and friends each carry documented weights. Every score comes with human-readable flags so you can see &lt;em&gt;why&lt;/em&gt; something is &lt;code&gt;critical&lt;/code&gt;, not just that it is. It handles both Manifest V2 and V3, and flags extensions abandoned for over a year — the quiet way risky code stays installed forever.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three input modes
&lt;/h2&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;"searchQueries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"password manager"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"categories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"extensions/productivity/tools"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxExtensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"minUsers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"onlyRiskLevels"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"critical"&lt;/span&gt;&lt;span class="p"&gt;]&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;Paste explicit extension URLs/IDs, run search queries, or enumerate whole categories — mixed in one run. Filters (&lt;code&gt;minUsers&lt;/code&gt;, &lt;code&gt;minRating&lt;/code&gt;, &lt;code&gt;onlyRiskLevels&lt;/code&gt;, &lt;code&gt;requireBroadHostAccess&lt;/code&gt;) run &lt;em&gt;before&lt;/em&gt; charging: filtered-out extensions are free. The example above returns exactly the shortlist a security reviewer wants — popular extensions with dangerous permission sets.&lt;/p&gt;

&lt;p&gt;It's not only for security teams. Extension developers use the same rows to track competitor ratings, user growth and update cadence; acquirers screen for abandoned extensions with big install bases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put it on a schedule
&lt;/h2&gt;

&lt;p&gt;The data rots fast — versions ship weekly, permissions change silently on update, new extensions appear daily. The useful setup is not one run, it's a standing audit:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run once with your allowlist (or a category) as input, sanity-check the output.&lt;/li&gt;
&lt;li&gt;On the actor page: &lt;strong&gt;⋯ menu → Schedule Actor&lt;/strong&gt;, cron &lt;code&gt;0 7 * * 1&lt;/code&gt; (weekly Monday morning fits most review cadences).&lt;/li&gt;
&lt;li&gt;Add a Google Sheets or Slack integration on &lt;em&gt;Run succeeded&lt;/em&gt;, filtered to &lt;code&gt;riskLevel&lt;/code&gt; in &lt;code&gt;high&lt;/code&gt;/&lt;code&gt;critical&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From then on, a permission escalation in an extension your org uses shows up in Slack Monday morning instead of in an incident report.&lt;/p&gt;

&lt;h2&gt;
  
  
  MCP / AI-agent angle
&lt;/h2&gt;

&lt;p&gt;The actor is exposed via &lt;a href="https://mcp.apify.com/" rel="noopener noreferrer"&gt;Apify's MCP server&lt;/a&gt;, so an AI agent can call it as a tool: &lt;em&gt;"audit these 30 extensions and summarize which ones can read cookies on all sites"&lt;/em&gt; becomes one tool call returning structured JSON the agent can reason over. Agent-driven security reviews are exactly the kind of repetitive, structured task this was built for.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I build pay-per-event scrapers for boards people refresh manually — &lt;a href="https://apify.com/tactful_anvil" rel="noopener noreferrer"&gt;the full portfolio is here&lt;/a&gt;. If you try the extension scraper and something's missing, open an issue on the actor; field requests routinely ship within days.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Clippers refresh three reward boards every morning. Here's the data stack that does it for them</title>
      <dc:creator>Mr Zack</dc:creator>
      <pubDate>Tue, 18 Aug 2026 19:12:50 +0000</pubDate>
      <link>https://dev.to/tactful_anvil/clippers-refresh-three-reward-boards-every-morning-heres-the-data-stack-that-does-it-for-them-3ghj</link>
      <guid>https://dev.to/tactful_anvil/clippers-refresh-three-reward-boards-every-morning-heres-the-data-stack-that-does-it-for-them-3ghj</guid>
      <description>&lt;p&gt;"Clipping" is the job where you cut short-form videos for a brand and get paid per 1,000 views. It went from niche to industry fast: Whop's Content Rewards board alone currently lists &lt;strong&gt;501 active campaigns with $2.64M in total budgets — $1.46M of it still unclaimed&lt;/strong&gt; (live numbers, scraped today).&lt;/p&gt;

&lt;p&gt;The problem: the money is spread across &lt;strong&gt;multiple boards that don't talk to each other&lt;/strong&gt;, and every one of them moves daily. MrBeast ran a campaign on Vyro that burned through its budget in days. Whop campaigns routinely fill up overnight. If you clip for a living, your morning routine is opening three tabs and eyeballing what changed.&lt;/p&gt;

&lt;p&gt;That's a data problem, not a hustle problem. So I built a scraper for each board. All three are HTTP-only, no login, and return normalized JSON you can pipe anywhere — Sheets, a Discord bot, your own dashboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Whop Content Rewards — the big board
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://apify.com/tactful_anvil/whop-content-rewards-scraper" rel="noopener noreferrer"&gt;Whop Content Rewards Scraper&lt;/a&gt; pulls every campaign from contentrewards.com in one run: reward per 1,000 views, total budget, budget spent/left, progress %, platforms, category, verification status.&lt;/p&gt;

&lt;p&gt;Today's board: 501 active campaigns, reward rates from under $0.10 to four figures per 1k views, and &lt;strong&gt;$1.46M in budgets not yet paid out&lt;/strong&gt;. Sorting by &lt;code&gt;budgetLeftUsd&lt;/code&gt; instead of scrolling the default order is the entire edge.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Vyro — small board, big spikes
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://apify.com/tactful_anvil/vyro-clipping-campaigns-scraper" rel="noopener noreferrer"&gt;Vyro Clipping Campaigns Scraper&lt;/a&gt; covers vyro.com — the marketplace MrBeast uses. The board is tiny (right now: literally one live campaign, a $250,000 MrBeast drop), but that's exactly why it needs a monitor, not a browser tab: when something lands here, it burns fast. MrBeast's previous campaign spent $20K in under 8 days.&lt;/p&gt;

&lt;p&gt;The scraper computes &lt;code&gt;remainingViews&lt;/code&gt;, &lt;code&gt;budgetSpentPct&lt;/code&gt;, &lt;code&gt;isFreshWithin24h&lt;/code&gt;, and an &lt;code&gt;opportunityScore&lt;/code&gt;, and takes a &lt;code&gt;freshWithinHours&lt;/code&gt; input — so a scheduled run only alerts you when something &lt;em&gt;new&lt;/em&gt; shows up.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. ClipAffiliates — the only board that shows your competition
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://apify.com/tactful_anvil/clipaffiliates-clipping-campaigns-scraper" rel="noopener noreferrer"&gt;ClipAffiliates Clipping Campaigns Scraper&lt;/a&gt; covers clipaffiliates.com (4 campaigns today, CPM $0.75–$2.00). Its unique field: &lt;strong&gt;&lt;code&gt;active_affiliates_count&lt;/code&gt;&lt;/strong&gt; — how many clippers are already working each campaign. No other clipping board publishes this.&lt;/p&gt;

&lt;p&gt;From that, the scraper derives &lt;code&gt;remainingUsdPerAffiliate&lt;/code&gt; (budget left ÷ people competing for it) and a &lt;code&gt;lowCompetition&lt;/code&gt; sort. A $500 pool with 85 affiliates on it is a worse bet than a $100 pool with 23. Now that's a number, not a vibe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why scheduled runs are the whole point
&lt;/h2&gt;

&lt;p&gt;None of this data is worth much as a one-off export. It's worth a lot as a &lt;strong&gt;diff&lt;/strong&gt;. The pattern for all three actors:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the actor page → &lt;strong&gt;Schedules&lt;/strong&gt; tab → create a schedule (e.g. every 6 hours, ~$0.01–0.05/run at these board sizes).&lt;/li&gt;
&lt;li&gt;Point the integration at Google Sheets, or use a webhook to push new rows to Discord/Slack.&lt;/li&gt;
&lt;li&gt;Filter on the freshness fields (&lt;code&gt;isFreshWithin24h&lt;/code&gt;, &lt;code&gt;fundedAt&lt;/code&gt;, &lt;code&gt;end_date&lt;/code&gt;) so you only see what changed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Clippers who do this see new campaigns hours before the people refreshing tabs — on boards where budgets are first-come-first-served, that's the difference between claiming a fresh $250k pool and reading about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest limitations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;These scrape &lt;strong&gt;public board data only&lt;/strong&gt; — no login, no private campaign details, no bypassing anything.&lt;/li&gt;
&lt;li&gt;Boards change their markup; the actors retry defensively and I fix breakage fast (the Whop one has run &amp;gt;800 times at &amp;gt;99% success).&lt;/li&gt;
&lt;li&gt;Vyro's board being 1 campaign today isn't a bug — it's a small marketplace. That's why it's priced per result: an empty-board check costs you nearly nothing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you clip — or you're building tooling for people who do — the three actors are &lt;a href="https://apify.com/tactful_anvil/whop-content-rewards-scraper" rel="noopener noreferrer"&gt;Whop CR&lt;/a&gt;, &lt;a href="https://apify.com/tactful_anvil/vyro-clipping-campaigns-scraper" rel="noopener noreferrer"&gt;Vyro&lt;/a&gt;, and &lt;a href="https://apify.com/tactful_anvil/clipaffiliates-clipping-campaigns-scraper" rel="noopener noreferrer"&gt;ClipAffiliates&lt;/a&gt;. Feedback and field requests welcome — reviews on the Apify listings genuinely help an indie dev.&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>datascience</category>
      <category>sidehustle</category>
      <category>api</category>
    </item>
    <item>
      <title>Immunefi lists $150M+ in bug bounties. The board doesn't tell you which ones are worth your weekend</title>
      <dc:creator>Mr Zack</dc:creator>
      <pubDate>Wed, 12 Aug 2026 00:37:46 +0000</pubDate>
      <link>https://dev.to/tactful_anvil/immunefi-lists-150m-in-bug-bounties-the-board-doesnt-tell-you-which-ones-are-worth-your-weekend-1i8l</link>
      <guid>https://dev.to/tactful_anvil/immunefi-lists-150m-in-bug-bounties-the-board-doesnt-tell-you-which-ones-are-worth-your-weekend-1i8l</guid>
      <description>&lt;p&gt;Immunefi's board lists ~190 bug bounty programs and ~60 audit competitions, with top bounties up to &lt;strong&gt;$15,000,000&lt;/strong&gt; (LayerZero). If you hunt Web3 bugs, you've scrolled it. And you've probably noticed the sort order: by vault TVL. That's a fine number for Immunefi to showcase — it's just not &lt;em&gt;your&lt;/em&gt; number.&lt;/p&gt;

&lt;p&gt;Your number is: &lt;strong&gt;how much friction stands between me and getting paid?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because the board hides the expensive part in each program's fine print:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;KYC required?&lt;/strong&gt; Excludes anonymous researchers entirely. On today's data: 132 of 248 programs require it, 116 don't.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pay-to-submit fee?&lt;/strong&gt; Some programs charge USDC just to file a report. 30 programs do; most researchers find out at submit time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proof of concept:&lt;/strong&gt; "not required" vs "required" vs "runnable" is the difference between an evening and a week.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invite-only?&lt;/strong&gt; You can't even join.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Comparing that across 248 programs means opening 248 pages. So I scraped it — the data is all public, HTTP-only, no login.&lt;/p&gt;

&lt;h2&gt;
  
  
  One row per program
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://apify.com/tactful_anvil/immunefi-bug-bounty-audit-competition-scraper" rel="noopener noreferrer"&gt;Immunefi Bug Bounty &amp;amp; Audit Competition Scraper&lt;/a&gt; pulls both boards in ~5 seconds and computes two scores per program:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;frictionScore&lt;/code&gt; (0–100, lower = easier to get paid):&lt;/strong&gt; KYC 35%, pay-to-submit fee 25%, PoC requirement 25%, invite-only 15%. Normalized over what the program actually publishes — unknown fields don't fake a score.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;opportunityScore&lt;/code&gt; (0–100, "worth my weekend?"):&lt;/strong&gt; bounty size 45% (log-scaled — bounties span four orders of magnitude), low friction 25%, program upkeep 15% (freshly updated = actually maintained), payout assurance 15% (funded vault + Safe Harbor + Immunefi Standard).&lt;br&gt;
&lt;/p&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;"project"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sky"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"board"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bug-bounty"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxBountyUsd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"kycRequired"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payToSubmit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"proofOfConceptType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"inviteOnly"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"frictionScore"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"daysSinceUpdate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;21.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"opportunityScore"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;88.8&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;A $10M max bounty &lt;strong&gt;with no KYC and no submit fee&lt;/strong&gt; is a very different object from a $10M bounty behind KYC + $500 USDC + runnable PoC. The default board renders them identically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three queries the board can't answer
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"Anonymous-friendly, big money":&lt;/strong&gt; &lt;code&gt;{ "kycRequired": false, "minMaxBountyUsd": 1000000, "sortBy": "opportunity" }&lt;/code&gt; — today that's a shortlist of 16 programs, Sky's $10M at the top.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Live audit competitions with a deadline":&lt;/strong&gt; competitions carry &lt;code&gt;rewardsPoolUsd&lt;/code&gt;, &lt;code&gt;endDate&lt;/code&gt; and &lt;code&gt;daysUntilEnd&lt;/code&gt; — deadline-driven work with a fixed pool, deduplicated against the bounty board.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Recently maintained only":&lt;/strong&gt; &lt;code&gt;daysSinceUpdate&lt;/code&gt; filters out programs nobody has touched in a year. A stale program page is a weak signal the triage queue is stale too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Schedule it
&lt;/h2&gt;

&lt;p&gt;The board changes daily (Immunefi updates program metrics every day, and competitions open/close on deadlines). One scheduled run per morning:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Actor page → ⋯ → &lt;strong&gt;Schedule&lt;/strong&gt;, cron &lt;code&gt;0 7 * * *&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Input: &lt;code&gt;{ "sortBy": "opportunity", "excludeInviteOnly": true }&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Full run over 248 programs costs about $0.30 (pay-per-event, from $1.20/1k results).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Actor ships a typed output schema and works over MCP, so an AI agent can call it as a tool — "find me no-KYC bounties over $1M updated this month" becomes a filter, not a scraping project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fair-use note
&lt;/h2&gt;

&lt;p&gt;Everything scraped is on Immunefi's public pages — no login, no private program data, no vulnerability reports, and the Actor doesn't help you &lt;em&gt;bypass&lt;/em&gt; anything (the friction fields tell you the rules; they don't break them). Rate is one HTTP request per board per run.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://apify.com/tactful_anvil/immunefi-bug-bounty-audit-competition-scraper" rel="noopener noreferrer"&gt;https://apify.com/tactful_anvil/immunefi-bug-bounty-audit-competition-scraper&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Found a program with wrong data, or want another field (languages, ecosystems and vault balances are already in there)? Issues tab on the Actor page — parser bugs get fixed.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>web3</category>
      <category>webscraping</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Most "big budget" clipping campaigns never pay. Here's how to spot them from one scrape</title>
      <dc:creator>Mr Zack</dc:creator>
      <pubDate>Wed, 12 Aug 2026 00:17:25 +0000</pubDate>
      <link>https://dev.to/tactful_anvil/most-big-budget-clipping-campaigns-never-pay-heres-how-to-spot-them-from-one-scrape-2ip0</link>
      <guid>https://dev.to/tactful_anvil/most-big-budget-clipping-campaigns-never-pay-heres-how-to-spot-them-from-one-scrape-2ip0</guid>
      <description>&lt;p&gt;If you clip short-form video for money, you know Whop Content Rewards: hundreds of live campaigns paying $0.15–$20 per 1,000 views. The discover page lets you sort by budget. That sort is quietly costing you nights of work.&lt;/p&gt;

&lt;p&gt;Here's the number that changed how I pick campaigns: &lt;strong&gt;on the live board right now, 21% of active campaigns have never paid out a single cent.&lt;/strong&gt; Big banner budget, $0 actually spent. A "$30,000 budget" campaign that has paid nobody in three weeks is not a $30,000 opportunity — it's a landing page.&lt;/p&gt;

&lt;p&gt;The problem: the board doesn't show you payout speed. You can see &lt;code&gt;budget&lt;/code&gt; and &lt;code&gt;budget left&lt;/code&gt;, but not &lt;em&gt;how fast the money is actually moving&lt;/em&gt; — and that's the only number that separates a campaign that pays from a campaign that poses.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trick: the page already contains everything you need
&lt;/h2&gt;

&lt;p&gt;Every campaign card on Whop publishes three things: when it was funded, how much has been spent, and how many creators joined. From one snapshot — no monitoring, no state between runs — you can derive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dailyBurnUsd        = budgetSpent / daysSinceFunded     → is money moving?
estimatedDaysLeft   = budgetLeft / dailyBurnUsd         → will it still be there?
payoutPerCreatorUsd = budgetSpent / creators            → what did the average clipper earn?
budgetPace          = "draining" | "healthy" | "slow" | "stalled"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last field is the shortcut. On today's board of 456 campaigns:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;pace&lt;/th&gt;
&lt;th&gt;meaning&lt;/th&gt;
&lt;th&gt;what to do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;draining&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&amp;lt;3 days of budget left&lt;/td&gt;
&lt;td&gt;skip — gone before your clip gains traction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;healthy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;3–60 days&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;this is where you clip&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;slow&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;60–180 days&lt;/td&gt;
&lt;td&gt;fine, but budget may outlive the campaign&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;stalled&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&amp;gt;180 days at current burn&lt;/td&gt;
&lt;td&gt;the "big budget" mirage — money posted, almost nobody paid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;zero paid out so far&lt;/td&gt;
&lt;td&gt;unproven; could be brand new, could be dead&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Real example from today: two campaigns, both showing ~$30K budget. One burns $255/day and has paid the average creator &lt;strong&gt;$75&lt;/strong&gt;. The other burns $19/day — at that rate its budget lasts &lt;em&gt;four years&lt;/em&gt;, which is a polite way of saying nobody is getting paid. On the default board they look identical.&lt;/p&gt;

&lt;h2&gt;
  
  
  I packaged this as an Apify Actor
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://apify.com/tactful_anvil/whop-content-rewards-scraper" rel="noopener noreferrer"&gt;Whop Content Rewards Scraper&lt;/a&gt; pulls the full board (~456 campaigns) in about 5 seconds, HTTP-only, and computes all of the above per row, plus an &lt;code&gt;opportunityScore&lt;/code&gt; that ranks by reward rate (35%), budget headroom (25%), competition (25%) and payout velocity (15%).&lt;/p&gt;

&lt;p&gt;One honesty note, because it's the part I got wrong first: an early version of the score treated empty campaigns as "low competition" and ranked them near the top. That's backwards — a campaign nobody has joined &lt;em&gt;and&lt;/em&gt; that has never paid is not uncontested, it's &lt;strong&gt;untested&lt;/strong&gt;, and the data can't tell those apart. The current version gives no free marks for emptiness: unproven campaigns still rank, they just can't outrank a campaign that demonstrably pays. The scoring weights are documented in the README so you can argue with them.&lt;br&gt;
&lt;/p&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;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"WINNA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rewardPerThousandViews"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"budgetLeftUsd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;11659.17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dailyBurnUsd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;272.67&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"estimatedDaysLeft"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;42.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"budgetPace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"healthy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"payoutPerCreatorUsd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;75.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"creators"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;164&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"opportunityScore"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;71.1&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;h2&gt;
  
  
  The daily recipe
&lt;/h2&gt;

&lt;p&gt;The actual decision — "where do I clip tonight?" — as one scheduled run:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Input: &lt;code&gt;{ "sortBy": "opportunity", "minEstimatedDaysLeft": 3, "minPayoutPerCreatorUsd": 5 }&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Schedule it daily in Apify Console (Actor → ⋯ → Schedule; cron &lt;code&gt;0 7 * * *&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Read the top 10 rows with your coffee. Campaigns that pay real money to real creators, ranked.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A full-board run costs well under a dollar (pay-per-event, from $1.50/1k results). Once a day is plenty — the board moves daily, not by the second.&lt;/p&gt;

&lt;h2&gt;
  
  
  For AI agents
&lt;/h2&gt;

&lt;p&gt;The Actor ships a typed output schema and works over MCP, so an agent can answer "which clipping campaigns are actually paying right now?" by calling it as a tool and filtering &lt;code&gt;budgetPace == "healthy"&lt;/code&gt; — no scraping code inside your agent.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://apify.com/tactful_anvil/whop-content-rewards-scraper" rel="noopener noreferrer"&gt;https://apify.com/tactful_anvil/whop-content-rewards-scraper&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I clip too. This exists because I got tired of finding out a "$30K budget" was a mirage after posting to it. Bug reports and field requests: Issues tab on the Actor page.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>automation</category>
      <category>datascience</category>
    </item>
  </channel>
</rss>
