{"id":887,"date":"2026-07-10T17:34:46","date_gmt":"2026-07-10T17:34:46","guid":{"rendered":"https:\/\/quickref.me\/blog\/?p=887"},"modified":"2026-07-10T17:34:46","modified_gmt":"2026-07-10T17:34:46","slug":"how-to-pull-structured-data-from-any-website-via-an-api-or-cli","status":"publish","type":"post","link":"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/","title":{"rendered":"How to pull structured data from any website via an API or CLI"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">You open a product page and see a price. Your code opens the same page and sees a few hundred nested divs, some inline scripts, images that load whenever they feel like it, and class names that will change next Tuesday. What you actually want out of all that is JSON: a title, a price, a couple of fields, done.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Doing this for one page is a five-minute job. Doing it for fifty sites that keep changing is where it gets annoying. The extraction is rarely the real problem. The problem is holding a steady output schema in front of sources that will not hold still, and catching it when one of them breaks before your database fills up with nulls. There are three ways to go about it, and each has its own headaches.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">Approach 1: parse the HTML yourself<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Grab the page, parse it, pull out what you need with CSS selectors.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import requests<\/span><\/p>\n<p><span style=\"font-weight: 400;\">from bs4 import BeautifulSoup<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">html = requests.get(&#8220;https:\/\/api.example.com\/product\/42&#8221;).text<\/span><\/p>\n<p><span style=\"font-weight: 400;\">soup = BeautifulSoup(html, &#8220;html.parser&#8221;)<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">data = {<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8220;title&#8221;: soup.select_one(&#8220;h1.product-title&#8221;).get_text(strip=True),<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0&#8220;price&#8221;: soup.select_one(&#8220;[data-price]&#8221;)[&#8220;data-price&#8221;],<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p><span style=\"font-weight: 400;\">print(data)<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">Cheap, fast, no real dependencies. Fine when you own the page or it barely changes.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The problem is upkeep. Your selectors lean on someone else&#8217;s HTML, and they never agreed to keep it stable for you. Somebody renames a class or ships an A\/B test, <\/span><span style=\"font-weight: 400;\">select_one<\/span><span style=\"font-weight: 400;\"> starts returning <\/span><span style=\"font-weight: 400;\">None<\/span><span style=\"font-weight: 400;\">, and you find out two weeks later when you check the table and half the rows are empty. Do this across thirty sites and you have basically signed up for a second job keeping selectors alive.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">Approach 2: drive a headless browser<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Plenty of pages ship almost nothing in the initial HTML and build the content with JavaScript after load. For those you need a real browser. Headless Chromium runs the page like a normal one and gives you the DOM once it has settled.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import { chromium } from &#8220;playwright&#8221;;<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">const browser = await chromium.launch();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">const page = await browser.newPage();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">await page.goto(&#8220;https:\/\/api.example.com\/feed&#8221;);<\/span><\/p>\n<p><span style=\"font-weight: 400;\">await page.waitForSelector(&#8220;.card&#8221;);<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">const items = await page.$$eval(&#8220;.card&#8221;, cards =&gt;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0cards.map(c =&gt; ({<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0name: c.querySelector(&#8220;h2&#8221;)?.innerText,<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0url: c.querySelector(&#8220;a&#8221;)?.href,<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0}))<\/span><\/p>\n<p><span style=\"font-weight: 400;\">);<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">await browser.close();<\/span><\/p>\n<p><span style=\"font-weight: 400;\">console.log(items);<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">This gets you past the JS-rendering wall that plain fetching runs into. You pay for it, though. A browser process per job, more RAM, slower runs, and a fresh set of timing bugs around when the content actually shows up. And you are still writing the same selectors, just with a much heavier thing running them.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">Approach 3: call a hosted API or CLI<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Here you stop doing the extraction yourself. You hand a URL to a service, it hands back structured data. The browser, the parsing, the retries, the layout changes, all of that is on them now.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The request is about as dull as it gets, which is the whole point:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">curl &#8220;https:\/\/api.example.com\/extract?url=https:\/\/target.site\/profile&#8221; \\<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0-H &#8220;Authorization: Bearer $TOKEN&#8221;<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">{<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8220;title&#8221;: &#8220;Jane Doe&#8221;,<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8220;headline&#8221;: &#8220;Staff Engineer&#8221;,<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8220;links&#8221;: [&#8220;https:\/\/janedoe.dev&#8221;],<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0&#8220;text&#8221;: &#8220;&#8230;&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">}<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">Same thing from a terminal, which is handy for scripts and one-off pulls:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">extract get &#8211;url &#8220;https:\/\/target.site\/profile&#8221; &#8211;format json<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">This is where something like<\/span><a href=\"https:\/\/anysite.io\"> <span style=\"font-weight: 400;\">Anysite<\/span><\/a><span style=\"font-weight: 400;\"> comes in. You give it a URL and it returns structured data over an API or CLI, with ready-made endpoints for the usual platforms (profiles, posts and comments, listings, company and filing data, maps results) and a general parser that hands back cleaned content, links and metadata as JSON when there is no specific endpoint for the site. You get a normalized object back instead of writing and nursing a custom selector for every place you scrape.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">A concrete flow<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Say you want the latest posts from a handful of public profiles. The DIY version means fetching each page, working out whether it needs a browser, writing selectors per site, and dealing with however each one handles pagination. Through a hosted call it turns into one loop:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">import requests<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">def posts_for(url):<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0r = requests.get(<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8220;https:\/\/api.example.com\/extract&#8221;,<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0params={&#8220;url&#8221;: url, &#8220;type&#8221;: &#8220;posts&#8221;},<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0headers={&#8220;Authorization&#8221;: f&#8221;Bearer {TOKEN}&#8221;},<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0r.raise_for_status()<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0return r.json()[&#8220;items&#8221;]<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">for profile in profiles:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0for post in posts_for(profile):<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0save(post[&#8220;id&#8221;], post[&#8220;text&#8221;], post[&#8220;timestamp&#8221;])<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">All the per-site weirdness sits behind the endpoint. Your code just reads a stable schema and stops caring which platform the URL points at.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">Extract responsibly, whatever route you pick<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">None of this gets you out of the basics. Read the site&#8217;s <\/span><span style=\"font-weight: 400;\">robots.txt<\/span><span style=\"font-weight: 400;\"> and terms before you start hammering it, and use the official API if there is one. Space your requests out, send a real user agent, and cache so you are not pulling the same URL over and over. Treat failures as normal rather than exceptional: retry with backoff, keep a list of URLs that keep dying, and get alerted when your success rate drops instead of finding out from an empty dashboard. A hosted service takes care of a good chunk of this, but how hard you hit someone&#8217;s site is still on you.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">When a hosted API or CLI wins<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Doing it yourself makes sense when the target is small, stable and yours: an internal tool, a single vendor page, a site whose markup you can keep an eye on. You keep full control and pull in nothing extra, and that counts for something.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Go with a hosted API or CLI when:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">You are pulling from a lot of sites, or sites you do not control.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">The pages need JavaScript to render, or actively fight bots.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">You want the same JSON shape across sources without maintaining a schema for each one.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">A quiet failure (stale data, missing records, a dashboard that is confidently wrong) costs you more than a per-request fee.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">It comes down to control against upkeep. Rolling your own is cheap to start and expensive to keep running against targets that keep moving. A service charges per call but eats the layout changes, the browser overhead and the retry logic that otherwise piles up in your code. Once you are past a few sources, that upkeep usually outweighs everything else, and handing it off is what stops your pipeline from falling apart while you are off building other things.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">So start with the simplest thing that survives your real targets. Parse by hand when the site is small and stable. Bring in a browser when the page will not render without JavaScript. Move to a hosted API or CLI when the number of sources, or the cost of things breaking, gets bigger than what you feel like maintaining yourself.<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>You open a product page and see a price. Your code opens the same page and sees a few hundred nested divs, some inline scripts, images that load whenever they &hellip; <a href=\"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/\" class=\"more-link\">Read More<\/a><\/p>\n","protected":false},"author":1,"featured_media":129,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-887","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","entry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>How to pull structured data from any website via an API or CLI - Blog QuickRef<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to pull structured data from any website via an API or CLI - Blog QuickRef\" \/>\n<meta property=\"og:description\" content=\"You open a product page and see a price. Your code opens the same page and sees a few hundred nested divs, some inline scripts, images that load whenever they &hellip; Read More\" \/>\n<meta property=\"og:url\" content=\"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog QuickRef\" \/>\n<meta property=\"article:published_time\" content=\"2026-07-10T17:34:46+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/quickref.me\/blog\/wp-content\/uploads\/2024\/01\/unnamed.png\" \/>\n\t<meta property=\"og:image:width\" content=\"512\" \/>\n\t<meta property=\"og:image:height\" content=\"341\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"tedm\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"tedm\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":[\"Article\",\"BlogPosting\"],\"@id\":\"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/\"},\"author\":{\"name\":\"tedm\",\"@id\":\"https:\/\/quickref.me\/blog\/#\/schema\/person\/781b09d7f4bdae81ce0d191fb1b1d5ec\"},\"headline\":\"How to pull structured data from any website via an API or CLI\",\"datePublished\":\"2026-07-10T17:34:46+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/\"},\"wordCount\":1145,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/quickref.me\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/quickref.me\/blog\/wp-content\/uploads\/2024\/01\/unnamed.png\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/\",\"url\":\"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/\",\"name\":\"How to pull structured data from any website via an API or CLI - Blog QuickRef\",\"isPartOf\":{\"@id\":\"https:\/\/quickref.me\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/quickref.me\/blog\/wp-content\/uploads\/2024\/01\/unnamed.png\",\"datePublished\":\"2026-07-10T17:34:46+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/#primaryimage\",\"url\":\"https:\/\/quickref.me\/blog\/wp-content\/uploads\/2024\/01\/unnamed.png\",\"contentUrl\":\"https:\/\/quickref.me\/blog\/wp-content\/uploads\/2024\/01\/unnamed.png\",\"width\":512,\"height\":341},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/quickref.me\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to pull structured data from any website via an API or CLI\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/quickref.me\/blog\/#website\",\"url\":\"https:\/\/quickref.me\/blog\/\",\"name\":\"Blog QuickRef\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/quickref.me\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/quickref.me\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/quickref.me\/blog\/#organization\",\"name\":\"Blog QuickRef\",\"url\":\"https:\/\/quickref.me\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/quickref.me\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/quickref.me\/blog\/wp-content\/uploads\/2023\/10\/cropped-wuickref.png\",\"contentUrl\":\"https:\/\/quickref.me\/blog\/wp-content\/uploads\/2023\/10\/cropped-wuickref.png\",\"width\":236,\"height\":63,\"caption\":\"Blog QuickRef\"},\"image\":{\"@id\":\"https:\/\/quickref.me\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/quickref.me\/blog\/#\/schema\/person\/781b09d7f4bdae81ce0d191fb1b1d5ec\",\"name\":\"tedm\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/quickref.me\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/2689288940b2c1525bf9633d5f4c4b96d14ab0593b0ec8d5404a1f968810e963?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/2689288940b2c1525bf9633d5f4c4b96d14ab0593b0ec8d5404a1f968810e963?s=96&d=mm&r=g\",\"caption\":\"tedm\"},\"sameAs\":[\"https:\/\/quickref.me\/blog\"],\"url\":\"https:\/\/quickref.me\/blog\/author\/tedm\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to pull structured data from any website via an API or CLI - Blog QuickRef","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/","og_locale":"en_US","og_type":"article","og_title":"How to pull structured data from any website via an API or CLI - Blog QuickRef","og_description":"You open a product page and see a price. Your code opens the same page and sees a few hundred nested divs, some inline scripts, images that load whenever they &hellip; Read More","og_url":"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/","og_site_name":"Blog QuickRef","article_published_time":"2026-07-10T17:34:46+00:00","og_image":[{"width":512,"height":341,"url":"https:\/\/quickref.me\/blog\/wp-content\/uploads\/2024\/01\/unnamed.png","type":"image\/png"}],"author":"tedm","twitter_card":"summary_large_image","twitter_misc":{"Written by":"tedm","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":["Article","BlogPosting"],"@id":"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/#article","isPartOf":{"@id":"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/"},"author":{"name":"tedm","@id":"https:\/\/quickref.me\/blog\/#\/schema\/person\/781b09d7f4bdae81ce0d191fb1b1d5ec"},"headline":"How to pull structured data from any website via an API or CLI","datePublished":"2026-07-10T17:34:46+00:00","mainEntityOfPage":{"@id":"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/"},"wordCount":1145,"commentCount":0,"publisher":{"@id":"https:\/\/quickref.me\/blog\/#organization"},"image":{"@id":"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/#primaryimage"},"thumbnailUrl":"https:\/\/quickref.me\/blog\/wp-content\/uploads\/2024\/01\/unnamed.png","inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/","url":"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/","name":"How to pull structured data from any website via an API or CLI - Blog QuickRef","isPartOf":{"@id":"https:\/\/quickref.me\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/#primaryimage"},"image":{"@id":"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/#primaryimage"},"thumbnailUrl":"https:\/\/quickref.me\/blog\/wp-content\/uploads\/2024\/01\/unnamed.png","datePublished":"2026-07-10T17:34:46+00:00","breadcrumb":{"@id":"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/#primaryimage","url":"https:\/\/quickref.me\/blog\/wp-content\/uploads\/2024\/01\/unnamed.png","contentUrl":"https:\/\/quickref.me\/blog\/wp-content\/uploads\/2024\/01\/unnamed.png","width":512,"height":341},{"@type":"BreadcrumbList","@id":"https:\/\/quickref.me\/blog\/how-to-pull-structured-data-from-any-website-via-an-api-or-cli\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/quickref.me\/blog\/"},{"@type":"ListItem","position":2,"name":"How to pull structured data from any website via an API or CLI"}]},{"@type":"WebSite","@id":"https:\/\/quickref.me\/blog\/#website","url":"https:\/\/quickref.me\/blog\/","name":"Blog QuickRef","description":"","publisher":{"@id":"https:\/\/quickref.me\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/quickref.me\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/quickref.me\/blog\/#organization","name":"Blog QuickRef","url":"https:\/\/quickref.me\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/quickref.me\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/quickref.me\/blog\/wp-content\/uploads\/2023\/10\/cropped-wuickref.png","contentUrl":"https:\/\/quickref.me\/blog\/wp-content\/uploads\/2023\/10\/cropped-wuickref.png","width":236,"height":63,"caption":"Blog QuickRef"},"image":{"@id":"https:\/\/quickref.me\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/quickref.me\/blog\/#\/schema\/person\/781b09d7f4bdae81ce0d191fb1b1d5ec","name":"tedm","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/quickref.me\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/2689288940b2c1525bf9633d5f4c4b96d14ab0593b0ec8d5404a1f968810e963?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/2689288940b2c1525bf9633d5f4c4b96d14ab0593b0ec8d5404a1f968810e963?s=96&d=mm&r=g","caption":"tedm"},"sameAs":["https:\/\/quickref.me\/blog"],"url":"https:\/\/quickref.me\/blog\/author\/tedm\/"}]}},"_links":{"self":[{"href":"https:\/\/quickref.me\/blog\/wp-json\/wp\/v2\/posts\/887","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/quickref.me\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/quickref.me\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/quickref.me\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/quickref.me\/blog\/wp-json\/wp\/v2\/comments?post=887"}],"version-history":[{"count":1,"href":"https:\/\/quickref.me\/blog\/wp-json\/wp\/v2\/posts\/887\/revisions"}],"predecessor-version":[{"id":888,"href":"https:\/\/quickref.me\/blog\/wp-json\/wp\/v2\/posts\/887\/revisions\/888"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/quickref.me\/blog\/wp-json\/wp\/v2\/media\/129"}],"wp:attachment":[{"href":"https:\/\/quickref.me\/blog\/wp-json\/wp\/v2\/media?parent=887"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/quickref.me\/blog\/wp-json\/wp\/v2\/categories?post=887"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/quickref.me\/blog\/wp-json\/wp\/v2\/tags?post=887"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}