<?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: Subscribe W</title>
    <description>The latest articles on DEV Community by Subscribe W (@subscribe_w_63ad30e24bf3c).</description>
    <link>https://dev.to/subscribe_w_63ad30e24bf3c</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%2F3628182%2F8d60daba-b7b6-485c-8ecc-d6f8ca005d41.png</url>
      <title>DEV Community: Subscribe W</title>
      <link>https://dev.to/subscribe_w_63ad30e24bf3c</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/subscribe_w_63ad30e24bf3c"/>
    <language>en</language>
    <item>
      <title>Extract PDF Links with JavaScript and Turn Them into a Download Batch</title>
      <dc:creator>Subscribe W</dc:creator>
      <pubDate>Mon, 05 Oct 2026 14:15:00 +0000</pubDate>
      <link>https://dev.to/subscribe_w_63ad30e24bf3c/extract-pdf-links-with-javascript-and-turn-them-into-a-download-batch-1jnp</link>
      <guid>https://dev.to/subscribe_w_63ad30e24bf3c/extract-pdf-links-with-javascript-and-turn-them-into-a-download-batch-1jnp</guid>
      <description>&lt;p&gt;A documentation page has the PDFs you need for a project: specifications, reference sheets, and a few sample documents. You want a local copy of the relevant files before starting work.&lt;/p&gt;

&lt;p&gt;You could open each link and save each file. You could also write a downloader. For a small, occasional collection, a useful middle ground is to extract the links, review the selection, and use a browser extension to manage the batch.&lt;/p&gt;

&lt;p&gt;This walkthrough starts with a JavaScript snippet you can use independently, then shows how to take the resulting URLs through a download workflow.&lt;/p&gt;

&lt;p&gt;Disclosure: we make &lt;a href="https://www.simplemassdownloader.com/" rel="noopener noreferrer"&gt;Simple Mass Downloader&lt;/a&gt;, the desktop Chrome extension used in the second half of this example.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Extract direct PDF links from the page
&lt;/h2&gt;

&lt;p&gt;On a page containing ordinary PDF links, open Chrome DevTools and select the Console. The following snippet reads anchor elements from the current document and prints a deduplicated URL list. It does not make network requests or start downloads.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;urls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a[href]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;baseURI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;pdf$/i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Skip links that cannot be parsed as URLs.&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The URL constructor resolves relative links against the document's base URL. Checking &lt;code&gt;pathname&lt;/code&gt; allows a link such as &lt;code&gt;/docs/spec.pdf?version=2&lt;/code&gt; to match, even though the full address does not end in &lt;code&gt;.pdf&lt;/code&gt;. See the MDN references for &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/URL/URL" rel="noopener noreferrer"&gt;URL resolution&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/URL/pathname" rel="noopener noreferrer"&gt;pathname&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Removing the fragment combines links such as &lt;code&gt;spec.pdf#page=2&lt;/code&gt; and &lt;code&gt;spec.pdf#page=8&lt;/code&gt;. Query parameters remain intact because they may select a version or carry information the server needs. The &lt;code&gt;Set&lt;/code&gt; removes identical resulting URLs; it does not compare file contents.&lt;/p&gt;

&lt;p&gt;Copy the printed list into a text file, with one URL per line. Review it before downloading.&lt;/p&gt;

&lt;h3&gt;
  
  
  Know what this snippet misses
&lt;/h3&gt;

&lt;p&gt;This is a deliberately narrow extraction rule. It finds anchors whose URL paths end in &lt;code&gt;.pdf&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It will miss download endpoints such as &lt;code&gt;/download?id=123&lt;/code&gt;, files behind intermediate document pages, links inside separate iframe documents, and resources loaded only after further interaction. A matching URL also does not prove that the server will return a PDF.&lt;/p&gt;

&lt;p&gt;If a document is missing, inspect its link and open it normally. That tells you whether to adjust the extraction rule, visit another page, or use the site's own download flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Review the list before transferring files
&lt;/h2&gt;

&lt;p&gt;Treat the URL list as a small input manifest. Check that it represents the collection you actually want.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove unrelated documents and obsolete versions.&lt;/li&gt;
&lt;li&gt;Open a representative link to confirm it returns the expected file.&lt;/li&gt;
&lt;li&gt;Keep source page addresses in a separate project note for context and attribution.&lt;/li&gt;
&lt;li&gt;Keep temporary or signed download URLs out of public repositories.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Preserving query parameters matters here. Two URLs with the same path may return different versions. Conversely, two different addresses may return the same document. URL deduplication alone cannot resolve that distinction.&lt;/p&gt;

&lt;p&gt;For a collection you need to reproduce regularly in CI, a maintained script with explicit inputs and logging may fit better. The browser workflow is useful when choosing the files is an interactive task.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Bring the selection into a download workflow
&lt;/h2&gt;

&lt;p&gt;In Simple Mass Downloader, paste the URLs or import the TXT list. Review the resource list and select the files you want to save.&lt;/p&gt;

&lt;p&gt;You can also start directly from a page: choose a resource type, click &lt;strong&gt;Scan this page&lt;/strong&gt;, and review the results in the Dashboard. Search matches resource URLs and link text. Domain and extension filters help narrow the selection.&lt;/p&gt;

&lt;p&gt;For resources spread across several pages, a multi-tab scan can collect from all tabs in the current window or from the tabs to the right of the current tab. Use that scope when you want a combined list; separate scans have separate results.&lt;/p&gt;

&lt;p&gt;When links lead to document landing pages, &lt;strong&gt;Find files in pages&lt;/strong&gt; can look for resources inside selected linked pages. The &lt;a href="https://www.simplemassdownloader.com/blog/download-all-pdfs" rel="noopener noreferrer"&gt;PDF download guide&lt;/a&gt; covers that workflow in more detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Choose filenames and a destination
&lt;/h2&gt;

&lt;p&gt;Before starting, inspect the filename previews. Several source sites may all offer a file called &lt;code&gt;download.pdf&lt;/code&gt;. Numbering and website names can help distinguish those files in the output.&lt;/p&gt;

&lt;p&gt;Choose the save mode based on what you will do with the collection:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Save mode&lt;/th&gt;
&lt;th&gt;Useful for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Default Download Folder&lt;/td&gt;
&lt;td&gt;Separate files managed through Chrome&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ZIP archive&lt;/td&gt;
&lt;td&gt;A modest collection you want to package together&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Choose a folder&lt;/td&gt;
&lt;td&gt;Saving directly into an authorized project directory&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;ZIP archives are assembled in the browser, so memory and archive limits matter. Direct-folder saving requires the Dashboard to remain open. Keep Chrome running while the batch is active.&lt;/p&gt;

&lt;p&gt;Try a few files first. Confirm the names and destination before expanding the selection.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Verify the saved result
&lt;/h2&gt;

&lt;p&gt;A download workflow needs an output check. Open a saved PDF and confirm that it is the document you expected. Compare the successful and failed items against your selection.&lt;/p&gt;

&lt;p&gt;Expired URLs, authentication requirements, and server request limits can still interrupt a batch. The extension provides automatic retries and completion checks for supported failures, but the source must still allow access. Review failed items, resolve the cause, and retry those items.&lt;/p&gt;

&lt;p&gt;If the collection will become a test fixture or another reproducible project input, record the source version and consider storing checksums alongside your own manifest. A filename alone does not establish that two downloads contain the same bytes.&lt;/p&gt;

&lt;p&gt;To try the browser workflow, the &lt;a href="https://www.simplemassdownloader.com/install#sample-files" rel="noopener noreferrer"&gt;installation page includes small sample files&lt;/a&gt;. Start there, then apply the same steps to a few documents from your project.&lt;/p&gt;

&lt;p&gt;What usually takes more work in your own download tasks: finding the right URLs, naming the files, or verifying what arrived?&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>downloader</category>
      <category>ai</category>
    </item>
    <item>
      <title>📌 GMB Scraper: A Simple Tool to Extract B2B Leads from Google My Business (GBP)</title>
      <dc:creator>Subscribe W</dc:creator>
      <pubDate>Tue, 25 Nov 2025 03:57:27 +0000</pubDate>
      <link>https://dev.to/subscribe_w_63ad30e24bf3c/gmb-scraper-a-simple-tool-to-extract-b2b-leads-from-google-my-business-gbp-3jc1</link>
      <guid>https://dev.to/subscribe_w_63ad30e24bf3c/gmb-scraper-a-simple-tool-to-extract-b2b-leads-from-google-my-business-gbp-3jc1</guid>
      <description>&lt;p&gt;If you work with local businesses — whether you're building a SaaS, doing lead generation, or running SEO audits — you probably spend a lot of time checking &lt;strong&gt;Google My Business (now Google Business Profile)&lt;/strong&gt; pages.&lt;/p&gt;

&lt;p&gt;They contain everything: phone numbers, websites, hours, categories, ratings, CID, Place IDs, and more.&lt;br&gt;
The problem is that Google doesn’t offer an easy way to extract or export this data at scale.&lt;/p&gt;

&lt;p&gt;That’s where &lt;strong&gt;GMB Scraper&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;p&gt;👉 Tool link: &lt;strong&gt;&lt;a href="https://www.gmbscraper.org/" rel="noopener noreferrer"&gt;https://www.gmbscraper.org/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;🔍 What is GMB Scraper?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GMB Scraper&lt;/strong&gt; is a lightweight Chrome extension that automatically extracts structured business data directly from &lt;strong&gt;Google Business Profile&lt;/strong&gt; pages.&lt;/p&gt;

&lt;p&gt;It pulls fields such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Business name&lt;/li&gt;
&lt;li&gt;Phone &amp;amp; website&lt;/li&gt;
&lt;li&gt;Address&lt;/li&gt;
&lt;li&gt;Opening hours&lt;/li&gt;
&lt;li&gt;Categories&lt;/li&gt;
&lt;li&gt;Reviews &amp;amp; rating&lt;/li&gt;
&lt;li&gt;CID / place_id / kg_id&lt;/li&gt;
&lt;li&gt;Social links&lt;/li&gt;
&lt;li&gt;Emails (auto-detected)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And lets you export everything as &lt;strong&gt;CSV or XLSX&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;⚡ Why It’s Useful for Developers &amp;amp; Automators&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you’re building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a B2B lead generation workflow&lt;/li&gt;
&lt;li&gt;a CRM enrichment pipeline&lt;/li&gt;
&lt;li&gt;a SaaS tool that needs Google business data&lt;/li&gt;
&lt;li&gt;an automation with Zapier / Make / n8n&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;then raw GBP data is incredibly valuable.&lt;/p&gt;

&lt;p&gt;GMB Scraper saves you from “open-tab → copy → paste → repeat” and gives you fully structured fields you can drop straight into your database or automation layer.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;🚀 Try It&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you work with GMB/GBP data regularly, this tool can save hours of manual work every week.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Check it out:&lt;/strong&gt; &lt;a href="https://www.gmbscraper.org/" rel="noopener noreferrer"&gt;https://www.gmbscraper.org/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>leadgeneration</category>
      <category>webscraping</category>
      <category>marketing</category>
    </item>
  </channel>
</rss>
