<?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: drew</title>
    <description>The latest articles on DEV Community by drew (@devteamdrew).</description>
    <link>https://dev.to/devteamdrew</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%2F4217732%2Ff234778e-a160-4687-947b-edc7edde004a.png</url>
      <title>DEV Community: drew</title>
      <link>https://dev.to/devteamdrew</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devteamdrew"/>
    <language>en</language>
    <item>
      <title>Get new UK planning applications near any postcode as a weekly spreadsheet (no code)</title>
      <dc:creator>drew</dc:creator>
      <pubDate>Sat, 31 Oct 2026 11:04:08 +0000</pubDate>
      <link>https://dev.to/devteamdrew/get-new-uk-planning-applications-near-any-postcode-as-a-weekly-spreadsheet-no-code-49ne</link>
      <guid>https://dev.to/devteamdrew/get-new-uk-planning-applications-near-any-postcode-as-a-weekly-spreadsheet-no-code-49ne</guid>
      <description>&lt;p&gt;Builders, solar installers, architects, surveyors and local journalists all watch the same thing: &lt;strong&gt;new planning applications&lt;/strong&gt;. Each council publishes them on its own portal, which means a different search form, layout and export button (when there is one) for every area you cover.&lt;/p&gt;

&lt;p&gt;This guide shows how to get them into one spreadsheet, filtered by keyword and distance from a postcode, and how to set it up so that every week you only receive the applications you haven't seen yet. No code is needed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclosure: I built the Apify Actor used here. The data comes from &lt;a href="https://www.planit.org.uk/" rel="noopener noreferrer"&gt;PlanIt&lt;/a&gt;, an open aggregator of UK council planning data. The Actor is a client for its public API.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;One row per application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;council, reference, address and postcode&lt;/li&gt;
&lt;li&gt;the description ("Installation of 12 roof-mounted solar panels...")&lt;/li&gt;
&lt;li&gt;application type and size (Small / Medium / Large)&lt;/li&gt;
&lt;li&gt;status (Undecided, Permitted, Conditions, Rejected, Withdrawn...)&lt;/li&gt;
&lt;li&gt;received, validated, decided and consultation-end dates&lt;/li&gt;
&lt;li&gt;latitude/longitude and a link to the original council page&lt;/li&gt;
&lt;li&gt;optional details: agent company, case officer, parish, and document and comment counts&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Open the Actor
&lt;/h2&gt;

&lt;p&gt;Go to &lt;a href="https://apify.com/devteamdrew/uk-planning-applications?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=uk-planning-applications-weekly-leads&amp;amp;utm_content=link-1" rel="noopener noreferrer"&gt;UK Planning Applications Scraper on Apify&lt;/a&gt; You can also browse recent applications by council on &lt;a href="https://rowsift.co.uk/planning-applications/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=uk-planning-applications-weekly-leads&amp;amp;utm_content=link-2" rel="noopener noreferrer"&gt;Rowsift&lt;/a&gt;. and click &lt;strong&gt;Try for free&lt;/strong&gt;. You'll need a free Apify account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Say what and where
&lt;/h2&gt;

&lt;p&gt;Example: house extensions within 5 km of central Leeds from the last 14 days.&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;"search"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"extension"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"postcode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LS1 4AP"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"radiusKm"&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;"recentDays"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxItems"&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="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;Other useful filters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;authorities&lt;/code&gt;: whole councils instead of a radius, e.g. &lt;code&gt;["Leeds", "Bradford"]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;appState&lt;/code&gt;: e.g. &lt;code&gt;"Permitted"&lt;/code&gt; to see only approved schemes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;appSize&lt;/code&gt;: &lt;code&gt;"Large"&lt;/code&gt; to focus on bigger developments&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;startDate&lt;/code&gt; / &lt;code&gt;endDate&lt;/code&gt;: a fixed window instead of "last N days"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keyword ideas by trade: &lt;code&gt;solar&lt;/code&gt;, &lt;code&gt;loft conversion&lt;/code&gt;, &lt;code&gt;HMO&lt;/code&gt;, &lt;code&gt;heat pump&lt;/code&gt;, &lt;code&gt;dropped kerb&lt;/code&gt;, &lt;code&gt;change of use&lt;/code&gt;, &lt;code&gt;demolition&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Export
&lt;/h2&gt;

&lt;p&gt;When the run finishes, open the &lt;strong&gt;Output&lt;/strong&gt; tab and export as CSV, Excel or JSON, or connect it to Google Sheets with Apify's integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Make it a weekly feed of only new applications
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Tick &lt;strong&gt;incremental&lt;/strong&gt; in the input. The Actor remembers what it already delivered for that same input and skips it next time, so you only pay for new rows.&lt;/li&gt;
&lt;li&gt;Create a &lt;strong&gt;Schedule&lt;/strong&gt; in Apify (e.g. every Monday 07:00).&lt;/li&gt;
&lt;li&gt;Optionally, add a Google Sheets or email integration so the new rows land somewhere you'll see them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You now have a Monday-morning list of fresh, local, relevant applications.&lt;/p&gt;

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

&lt;p&gt;Pay per result, with no subscription to the Actor: &lt;strong&gt;$0.012 per application&lt;/strong&gt; (about $12 per 1,000) plus a $0.003 start fee per run. Detailed rows (&lt;code&gt;includeDetails&lt;/code&gt;) are $0.02 each. A weekly local search usually returns a handful to a few dozen rows (that Leeds search returned 8 when I tested it on 31 Oct 2026), so it costs pennies a week. Apify's free plan includes monthly platform credit, enough to try it.&lt;/p&gt;

&lt;h2&gt;
  
  
  For developers
&lt;/h2&gt;

&lt;p&gt;You can call the same thing from code or from an AI agent (the Actor works as an MCP tool):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://api.apify.com/v2/acts/devteamdrew~uk-planning-applications/run-sync-get-dataset-items?token=&lt;/span&gt;&lt;span class="nv"&gt;$APIFY_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"search":"extension","postcode":"LS1 4AP","radiusKm":5,"recentDays":14,"maxItems":50}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set &lt;code&gt;"outputFormat": "llm"&lt;/code&gt; to get a compact Markdown block per application for RAG or summarising.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes and limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Coverage and freshness depend on PlanIt's council feeds. Most English, Welsh and Scottish councils are included, but a few update slowly.&lt;/li&gt;
&lt;li&gt;This is public planning data. If you use it for outreach, follow UK GDPR and PECR, and don't treat individual applicants' addresses as a marketing list.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Questions or a council that looks wrong? Leave a comment and I'll take a look.&lt;/p&gt;

</description>
      <category>uk</category>
      <category>nocode</category>
      <category>tutorial</category>
      <category>data</category>
    </item>
    <item>
      <title>Scrape Bluesky posts and profiles without an API key</title>
      <dc:creator>drew</dc:creator>
      <pubDate>Fri, 30 Oct 2026 17:02:16 +0000</pubDate>
      <link>https://dev.to/devteamdrew/scrape-bluesky-posts-and-profiles-without-an-api-key-i10</link>
      <guid>https://dev.to/devteamdrew/scrape-bluesky-posts-and-profiles-without-an-api-key-i10</guid>
      <description>&lt;p&gt;Bluesky is unusually open: almost everything public is available through the AT Protocol's public &lt;strong&gt;AppView API&lt;/strong&gt; at &lt;code&gt;public.api.bsky.app&lt;/code&gt; / &lt;code&gt;api.bsky.app&lt;/code&gt;, with no login. (Tested 30 Oct 2026: post search returned 403 on &lt;code&gt;public.api.bsky.app&lt;/code&gt; but worked on &lt;code&gt;api.bsky.app&lt;/code&gt;. Profiles and feeds worked on both.) Here's how to use it directly, and how to get the same data with no code at all.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclosure: I built the Apify Actor shown in part 2.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Part 1: The raw API (no key needed)
&lt;/h2&gt;

&lt;p&gt;Search recent posts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.bsky.app/xrpc/app.bsky.feed.searchPosts?q=web%20scraping&amp;amp;sort=latest&amp;amp;limit=5"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look up a profile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=bsky.app"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get an account's posts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://public.api.bsky.app/xrpc/app.bsky.feed.getAuthorFeed?actor=bsky.app&amp;amp;limit=10"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works fine for one-off calls. You'll start writing plumbing once you need cursor pagination, rate-limit backoff, flattening nested &lt;code&gt;record&lt;/code&gt;/&lt;code&gt;embed&lt;/code&gt; objects, extracting links and hashtags from facets, and remembering which posts you've already seen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2: No-code with the Bluesky Scraper Actor
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://apify.com/devteamdrew/bluesky-scraper?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=bluesky-without-api-key&amp;amp;utm_content=link-1" rel="noopener noreferrer"&gt;Bluesky Scraper on Apify&lt;/a&gt; handles that plumbing. Pick a mode (&lt;strong&gt;Search posts&lt;/strong&gt;, &lt;strong&gt;Search profiles&lt;/strong&gt; or &lt;strong&gt;Posts from accounts&lt;/strong&gt;) and enter queries. Bluesky's search syntax works, e.g. &lt;code&gt;from:handle&lt;/code&gt;, &lt;code&gt;lang:en&lt;/code&gt; and &lt;code&gt;#hashtags&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Input from a real run:&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;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"searchPosts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"queries"&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;"web scraping"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxItems"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"latest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"outputFormat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"both"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That run finished in about 3 seconds. One of the items, exactly as returned:&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"post"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://bsky.app/profile/hugovalters.bsky.social/post/3mz3rucjn3h2o"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Fill web forms from a JSON file using Playwright. 136 lines, intermediate level, takes a screenshot after submit so you can verify. Built for QA and smoke tests. #python #playwright #scraping https://www.valtersit.com/python/playwright-browser-automation-for-form-filling/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"createdAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-30T12:30:00.600753Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"authorHandle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hugovalters.bsky.social"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"likeCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"repostCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"replyCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"quoteCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"links"&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;"https://www.valtersit.com/python/playwright-browser-automation-for-form-filling/"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"imageCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"isReply"&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;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"web scraping"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"markdown"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"## Post by @hugovalters.bsky.social&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;- **url:** https://bsky.app/profile/hugovalters.bsky.social/post/3mz3rucjn3h2o&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;- **date:** 2026-10-30T12:30:00.600753Z&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;- **likes:** 0 ..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;outputFormat: "both"&lt;/code&gt; adds the &lt;code&gt;markdown&lt;/code&gt; field, a compact version that's easy to drop into an LLM prompt or a RAG index.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monitoring a keyword or brand
&lt;/h3&gt;

&lt;p&gt;Turn on &lt;strong&gt;incremental mode&lt;/strong&gt; and add a schedule (for example, hourly). Each run returns only posts it hasn't returned before, so you can wire a webhook to Slack, a Google Sheet or your own endpoint without dealing with duplicates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exporting
&lt;/h3&gt;

&lt;p&gt;Dataset → Export → CSV/Excel/JSON, or call the run's dataset API from your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost
&lt;/h2&gt;

&lt;p&gt;$0.003 per run plus $0.001 per result, so 1,000 posts cost about $1. Small tests fit in Apify's free monthly credit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Be a good citizen
&lt;/h2&gt;

&lt;p&gt;It's public data, but it's still people's posts. Respect deletions, don't build profiles on individuals, and follow Bluesky's developer guidelines and UK/EU GDPR if you store personal data.&lt;/p&gt;

&lt;p&gt;What would you monitor on Bluesky? Let me know in the comments.&lt;/p&gt;

</description>
      <category>bluesky</category>
      <category>webscraping</category>
      <category>api</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to pull UK Companies House data into a spreadsheet without code</title>
      <dc:creator>drew</dc:creator>
      <pubDate>Fri, 30 Oct 2026 17:01:41 +0000</pubDate>
      <link>https://dev.to/devteamdrew/how-to-pull-uk-companies-house-data-into-a-spreadsheet-without-code-5b6i</link>
      <guid>https://dev.to/devteamdrew/how-to-pull-uk-companies-house-data-into-a-spreadsheet-without-code-5b6i</guid>
      <description>&lt;p&gt;If you've ever needed a list of UK companies (suppliers to check, leads in a sector, or the directors behind a competitor), you've probably copied rows out of the Companies House website one at a time. The data is public and comes from a good official API, but that API needs a key, pagination and some JSON wrangling.&lt;/p&gt;

&lt;p&gt;This guide shows how to get the same data into a spreadsheet &lt;strong&gt;without writing any code&lt;/strong&gt;, using a ready-made Apify Actor that calls the official Companies House Public Data API for you.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclosure: I built the Actor used here. Everything it returns comes from Companies House's own API.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;For each company:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;company number, name, status (active/dissolved) and type (ltd, plc…)&lt;/li&gt;
&lt;li&gt;incorporation and dissolution dates&lt;/li&gt;
&lt;li&gt;SIC codes (industry)&lt;/li&gt;
&lt;li&gt;registered address and postcode&lt;/li&gt;
&lt;li&gt;next accounts and confirmation statement due dates&lt;/li&gt;
&lt;li&gt;flags for charges and insolvency history&lt;/li&gt;
&lt;li&gt;optionally: &lt;strong&gt;current and past officers&lt;/strong&gt; (directors, secretaries) and the &lt;strong&gt;25 most recent filings&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Open the Actor
&lt;/h2&gt;

&lt;p&gt;Go to &lt;a href="https://apify.com/devteamdrew/companies-house-scraper?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=companies-house-to-spreadsheet&amp;amp;utm_content=link-1" rel="noopener noreferrer"&gt;Companies House Scraper on Apify&lt;/a&gt; and click &lt;strong&gt;Try for free&lt;/strong&gt;. You'll need a free Apify account. You don't need your own Companies House key, but you can paste one in for dedicated rate limits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Enter what you're looking for
&lt;/h2&gt;

&lt;p&gt;You can search by name/keyword, or paste exact company numbers. Here's the input I used:&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;"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;"tesco"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxItems"&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;"includeOfficers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;Other useful switches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Only active companies&lt;/strong&gt;: skips dissolved and liquidated ones&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Include filing history&lt;/strong&gt;: adds recent filings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Incremental mode&lt;/strong&gt;: on a schedule, returns only companies you haven't already received (handy for watching new incorporations matching a keyword)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3: Run it and look at the output
&lt;/h2&gt;

&lt;p&gt;That run returned 5 companies in about 8 seconds. Here's the first record, trimmed to the first two officers:&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;"companyNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"00445790"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://find-and-update.company-information.service.gov.uk/company/00445790"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TESCO PLC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"plc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"incorporatedOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1947-11-27"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sicCodes"&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;"47110"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"registeredAddress"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tesco House, Shire Park, Kestrel Way, Welwyn Garden City, AL7 1GA, United Kingdom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"postcode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AL7 1GA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"jurisdiction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"england-wales"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"accountsNextDue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2027-08-26"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confirmationStatementNextDue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2027-07-02"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hasCharges"&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;"hasInsolvencyHistory"&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;"officers"&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TAYLOR, Christopher Jon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"secretary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"appointedOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-04-14"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"resignedOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BETHELL, Melissa"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"director"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"appointedOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2018-09-24"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"resignedOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"nationality"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"British"&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;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;h2&gt;
  
  
  Step 4: Export to a spreadsheet
&lt;/h2&gt;

&lt;p&gt;In the run's &lt;strong&gt;Storage → Dataset&lt;/strong&gt; tab, click &lt;strong&gt;Export&lt;/strong&gt; and choose &lt;strong&gt;CSV&lt;/strong&gt; or &lt;strong&gt;Excel&lt;/strong&gt;. Fields are flat, so they open as clean columns. To send rows straight to Google Sheets, use Apify's Google Sheets integration on the Actor's &lt;strong&gt;Integrations&lt;/strong&gt; tab, or schedule the Actor and add the integration so the sheet updates itself.&lt;/p&gt;

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

&lt;p&gt;Pricing is pay-per-event: $0.003 per run start, $0.008 per company, and $0.02 per enriched company (with officers/filings). So 100 basic company records cost about $0.80 plus the start fee. Apify's free plan includes monthly usage credit, which covers small tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ideas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lead lists:&lt;/strong&gt; search a sector keyword ("coffee roasters", "solar"), keep active companies, export to CSV.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supplier checks:&lt;/strong&gt; paste company numbers, turn on officers and filings, and look for insolvency flags.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New-company watch:&lt;/strong&gt; schedule daily with incremental mode on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A note on personal data: officer names are public register data, but if you use them for outreach, UK GDPR still applies (legitimate interest, an opt-out, and no special-category data).&lt;/p&gt;

&lt;p&gt;Questions or missing fields? Leave a comment, I'm actively improving it.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>uk</category>
      <category>nocode</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
