## Table of Contents

- [Start with a single field](#start-with-a-single-field)
  - [CLI Microlink API example](#cli-microlink-api-example)
  - [cURL Microlink API example](#curl-microlink-api-example)
  - [JavaScript Microlink API example](#javascript-microlink-api-example)
  - [Python Microlink API example](#python-microlink-api-example)
  - [Ruby Microlink API example](#ruby-microlink-api-example)
  - [PHP Microlink API example](#php-microlink-api-example)
  - [Golang Microlink API example](#golang-microlink-api-example)
- [Extract a collection](#extract-a-collection)
  - [CLI Microlink API example](#cli-microlink-api-example-1)
  - [cURL Microlink API example](#curl-microlink-api-example-1)
  - [JavaScript Microlink API example](#javascript-microlink-api-example-1)
  - [Python Microlink API example](#python-microlink-api-example-1)
  - [Ruby Microlink API example](#ruby-microlink-api-example-1)
  - [PHP Microlink API example](#php-microlink-api-example-1)
  - [Golang Microlink API example](#golang-microlink-api-example-1)
- [Return structured objects](#return-structured-objects)
  - [CLI Microlink API example](#cli-microlink-api-example-2)
  - [cURL Microlink API example](#curl-microlink-api-example-2)
  - [JavaScript Microlink API example](#javascript-microlink-api-example-2)
  - [Python Microlink API example](#python-microlink-api-example-2)
  - [Ruby Microlink API example](#ruby-microlink-api-example-2)
  - [PHP Microlink API example](#php-microlink-api-example-2)
  - [Golang Microlink API example](#golang-microlink-api-example-2)
- [Use fallback rules](#use-fallback-rules)
  - [CLI Microlink API example](#cli-microlink-api-example-3)
  - [cURL Microlink API example](#curl-microlink-api-example-3)
  - [JavaScript Microlink API example](#javascript-microlink-api-example-3)
  - [Python Microlink API example](#python-microlink-api-example-3)
  - [Ruby Microlink API example](#ruby-microlink-api-example-3)
  - [PHP Microlink API example](#php-microlink-api-example-3)
  - [Golang Microlink API example](#golang-microlink-api-example-3)
- [Pick the right output form](#pick-the-right-output-form)
  - [CLI Microlink API example](#cli-microlink-api-example-4)
  - [cURL Microlink API example](#curl-microlink-api-example-4)
  - [JavaScript Microlink API example](#javascript-microlink-api-example-4)
  - [Python Microlink API example](#python-microlink-api-example-4)
  - [Ruby Microlink API example](#ruby-microlink-api-example-4)
  - [PHP Microlink API example](#php-microlink-api-example-4)
  - [Golang Microlink API example](#golang-microlink-api-example-4)
- [Extract JSON](#extract-json)
  - [CLI Microlink API example](#cli-microlink-api-example-5)
  - [cURL Microlink API example](#curl-microlink-api-example-5)
  - [JavaScript Microlink API example](#javascript-microlink-api-example-5)
  - [Python Microlink API example](#python-microlink-api-example-5)
  - [Ruby Microlink API example](#ruby-microlink-api-example-5)
  - [PHP Microlink API example](#php-microlink-api-example-5)
  - [Golang Microlink API example](#golang-microlink-api-example-5)
- [Use evaluate for custom values](#use-evaluate-for-custom-values)
  - [CLI Microlink API example](#cli-microlink-api-example-6)
  - [cURL Microlink API example](#curl-microlink-api-example-6)
  - [JavaScript Microlink API example](#javascript-microlink-api-example-6)
  - [Python Microlink API example](#python-microlink-api-example-6)
  - [Ruby Microlink API example](#ruby-microlink-api-example-6)
  - [PHP Microlink API example](#php-microlink-api-example-6)
  - [Golang Microlink API example](#golang-microlink-api-example-6)
- [Rule references](#rule-references)
- [Next step](#next-step)

---

[API](https://microlink.io/docs/api/getting-started/overview)

[GUIDES](https://microlink.io/docs/guides) [MQL](https://microlink.io/docs/mql/getting-started/overview) [SDK](https://microlink.io/docs/sdk/getting-started/overview) [CARDS](https://microlink.io/docs/cards/getting-started/overview)

API GUIDES MQL SDK CARDS

Getting Started

[Overview](https://microlink.io/docs/guides)

[What is Microlink](https://microlink.io/docs/guides/what-is-microlink)

[Screenshot](https://microlink.io/docs/guides/screenshot)

[Customizing output](https://microlink.io/docs/guides/screenshot/customizing-output)

[Browser settings](https://microlink.io/docs/guides/screenshot/browser-settings)

[Page interaction](https://microlink.io/docs/guides/screenshot/page-interaction)

[Delivery and embedding](https://microlink.io/docs/guides/screenshot/embedding)

[Caching and performance](https://microlink.io/docs/guides/screenshot/caching-and-performance)

[Private pages](https://microlink.io/docs/guides/screenshot/private-pages)

[Troubleshooting](https://microlink.io/docs/guides/screenshot/troubleshooting)

[Data extraction](https://microlink.io/docs/guides/data-extraction)

[Defining rules](https://microlink.io/docs/guides/data-extraction/defining-rules)

[Page preparation](https://microlink.io/docs/guides/data-extraction/page-preparation)

[Delivery and response shaping](https://microlink.io/docs/guides/data-extraction/delivery-and-response)

[Caching and performance](https://microlink.io/docs/guides/data-extraction/caching-and-performance)

[Private pages](https://microlink.io/docs/guides/data-extraction/private-pages)

[Troubleshooting](https://microlink.io/docs/guides/data-extraction/troubleshooting)

[Embed](https://microlink.io/docs/guides/embed)

[SDK](https://microlink.io/docs/guides/embed/sdk)

[Iframe parameter](https://microlink.io/docs/guides/embed/iframe)

[Custom HTML/CSS](https://microlink.io/docs/guides/embed/metadata-api)

[Custom previews with AI](https://microlink.io/docs/guides/embed/custom-previews-with-ai)

[Caching and performance](https://microlink.io/docs/guides/embed/caching-and-performance)

[Private pages and proxy](https://microlink.io/docs/guides/embed/private-pages-and-proxy)

[Troubleshooting](https://microlink.io/docs/guides/embed/troubleshooting)

[Markdown](https://microlink.io/docs/guides/markdown)

[Choosing scope](https://microlink.io/docs/guides/markdown/choosing-scope)

[Delivery and response shaping](https://microlink.io/docs/guides/markdown/delivery-and-response)

[Function](https://microlink.io/docs/guides/function)

[Writing functions](https://microlink.io/docs/guides/function/writing-functions)

[Browser interaction](https://microlink.io/docs/guides/function/browser-interaction)

[Profiling and performance](https://microlink.io/docs/guides/function/profiling-and-performance)

[Troubleshooting](https://microlink.io/docs/guides/function/troubleshooting)

[PDF](https://microlink.io/docs/guides/pdf)

[Page size and layout](https://microlink.io/docs/guides/pdf/page-size-and-layout)

[Page preparation](https://microlink.io/docs/guides/pdf/page-preparation)

[Delivery and embedding](https://microlink.io/docs/guides/pdf/embedding)

[Caching and performance](https://microlink.io/docs/guides/pdf/caching-and-performance)

[Private pages](https://microlink.io/docs/guides/pdf/private-pages)

[Troubleshooting](https://microlink.io/docs/guides/pdf/troubleshooting)

[Metadata](https://microlink.io/docs/guides/metadata)

[Choosing fields](https://microlink.io/docs/guides/metadata/choosing-fields)

[Extending results](https://microlink.io/docs/guides/metadata/extending-results)

[Delivery and response shaping](https://microlink.io/docs/guides/metadata/delivery-and-response)

[Page preparation](https://microlink.io/docs/guides/metadata/page-preparation)

[Caching and performance](https://microlink.io/docs/guides/metadata/caching-and-performance)

[Private pages](https://microlink.io/docs/guides/metadata/private-pages)

[Troubleshooting](https://microlink.io/docs/guides/metadata/troubleshooting)

[Insights](https://microlink.io/docs/guides/insights)

[Technology detection](https://microlink.io/docs/guides/insights/technology-detection)

[Lighthouse reports](https://microlink.io/docs/guides/insights/lighthouse-reports)

[Caching and performance](https://microlink.io/docs/guides/insights/caching-and-performance)

[Troubleshooting](https://microlink.io/docs/guides/insights/troubleshooting)

[Common patterns](https://microlink.io/docs/guides/common/caching)

[Caching patterns](https://microlink.io/docs/guides/common/caching)

[Private pages](https://microlink.io/docs/guides/common/private-pages)

[Proxy](https://microlink.io/docs/guides/common/proxy)

[Troubleshooting](https://microlink.io/docs/guides/common/troubleshooting)

[Production patterns](https://microlink.io/docs/guides/common/production-patterns)

API GUIDES MQL SDK CARDS

Getting Started

[Overview](https://microlink.io/docs/guides)

[What is Microlink](https://microlink.io/docs/guides/what-is-microlink)

[Screenshot](https://microlink.io/docs/guides/screenshot)

[Customizing output](https://microlink.io/docs/guides/screenshot/customizing-output)

[Browser settings](https://microlink.io/docs/guides/screenshot/browser-settings)

[Page interaction](https://microlink.io/docs/guides/screenshot/page-interaction)

[Delivery and embedding](https://microlink.io/docs/guides/screenshot/embedding)

[Caching and performance](https://microlink.io/docs/guides/screenshot/caching-and-performance)

[Private pages](https://microlink.io/docs/guides/screenshot/private-pages)

[Troubleshooting](https://microlink.io/docs/guides/screenshot/troubleshooting)

[Data extraction](https://microlink.io/docs/guides/data-extraction)

[Defining rules](https://microlink.io/docs/guides/data-extraction/defining-rules)

[Page preparation](https://microlink.io/docs/guides/data-extraction/page-preparation)

[Delivery and response shaping](https://microlink.io/docs/guides/data-extraction/delivery-and-response)

[Caching and performance](https://microlink.io/docs/guides/data-extraction/caching-and-performance)

[Private pages](https://microlink.io/docs/guides/data-extraction/private-pages)

[Troubleshooting](https://microlink.io/docs/guides/data-extraction/troubleshooting)

[Embed](https://microlink.io/docs/guides/embed)

[SDK](https://microlink.io/docs/guides/embed/sdk)

[Iframe parameter](https://microlink.io/docs/guides/embed/iframe)

[Custom HTML/CSS](https://microlink.io/docs/guides/embed/metadata-api)

[Custom previews with AI](https://microlink.io/docs/guides/embed/custom-previews-with-ai)

[Caching and performance](https://microlink.io/docs/guides/embed/caching-and-performance)

[Private pages and proxy](https://microlink.io/docs/guides/embed/private-pages-and-proxy)

[Troubleshooting](https://microlink.io/docs/guides/embed/troubleshooting)

[Markdown](https://microlink.io/docs/guides/markdown)

[Choosing scope](https://microlink.io/docs/guides/markdown/choosing-scope)

[Delivery and response shaping](https://microlink.io/docs/guides/markdown/delivery-and-response)

[Function](https://microlink.io/docs/guides/function)

[Writing functions](https://microlink.io/docs/guides/function/writing-functions)

[Browser interaction](https://microlink.io/docs/guides/function/browser-interaction)

[Profiling and performance](https://microlink.io/docs/guides/function/profiling-and-performance)

[Troubleshooting](https://microlink.io/docs/guides/function/troubleshooting)

[PDF](https://microlink.io/docs/guides/pdf)

[Page size and layout](https://microlink.io/docs/guides/pdf/page-size-and-layout)

[Page preparation](https://microlink.io/docs/guides/pdf/page-preparation)

[Delivery and embedding](https://microlink.io/docs/guides/pdf/embedding)

[Caching and performance](https://microlink.io/docs/guides/pdf/caching-and-performance)

[Private pages](https://microlink.io/docs/guides/pdf/private-pages)

[Troubleshooting](https://microlink.io/docs/guides/pdf/troubleshooting)

[Metadata](https://microlink.io/docs/guides/metadata)

[Choosing fields](https://microlink.io/docs/guides/metadata/choosing-fields)

[Extending results](https://microlink.io/docs/guides/metadata/extending-results)

[Delivery and response shaping](https://microlink.io/docs/guides/metadata/delivery-and-response)

[Page preparation](https://microlink.io/docs/guides/metadata/page-preparation)

[Caching and performance](https://microlink.io/docs/guides/metadata/caching-and-performance)

[Private pages](https://microlink.io/docs/guides/metadata/private-pages)

[Troubleshooting](https://microlink.io/docs/guides/metadata/troubleshooting)

[Insights](https://microlink.io/docs/guides/insights)

[Technology detection](https://microlink.io/docs/guides/insights/technology-detection)

[Lighthouse reports](https://microlink.io/docs/guides/insights/lighthouse-reports)

[Caching and performance](https://microlink.io/docs/guides/insights/caching-and-performance)

[Troubleshooting](https://microlink.io/docs/guides/insights/troubleshooting)

[Common patterns](https://microlink.io/docs/guides/common/caching)

[Caching patterns](https://microlink.io/docs/guides/common/caching)

[Private pages](https://microlink.io/docs/guides/common/private-pages)

[Proxy](https://microlink.io/docs/guides/common/proxy)

[Troubleshooting](https://microlink.io/docs/guides/common/troubleshooting)

[Production patterns](https://microlink.io/docs/guides/common/production-patterns)

[Copy for LLM](https://microlink.io/docs/guides/data-extraction/defining-rules.md "Copy content for LLM")

\|

[View as Markdown](https://microlink.io/docs/guides/data-extraction/defining-rules.md "View content as Markdown")

Good extraction starts with good rule design. The goal is not to scrape everything blindly, but to declare the smallest set of fields your application actually needs.

## Start with a single field

The simplest rule targets one element and extracts one value:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://example.com' URL with 'data' & 'meta' API parameters:

### CLI Microlink API example

```bash
microlink https://example.com&data.title.selector=h1&data.title.attr=text
```

### cURL Microlink API example

```bash
curl -G "https://api.microlink.io" \
  -d "url=https://example.com" \
  -d "data.title.selector=h1" \
  -d "data.title.attr=text" \
  -d "meta=false"
```

### JavaScript Microlink API example

```javascript
import mql from '@microlink/mql'

const { data } = await mql('https://example.com', {
  data: {
    title: {
      selector: "h1",
      attr: "text"
    }
  },
  meta: false
})
```

### Python Microlink API example

```python
import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://example.com",
    "data.title.selector": "h1",
    "data.title.attr": "text",
    "meta": "false"
}

response = requests.get(url, params=querystring)

print(response.json())
```

### Ruby Microlink API example

```ruby
require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://example.com",
  data.title.selector: "h1",
  data.title.attr: "text",
  meta: "false"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body
```

### PHP Microlink API example

```php
<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://example.com",
    "data.title.selector" => "h1",
    "data.title.attr" => "text",
    "meta" => "false"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}
```

### Golang Microlink API example

```
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    q := u.Query()
    q.Set("url", "https://example.com")
    q.Set("data.title.selector", "h1")
    q.Set("data.title.attr", "text")
    q.Set("meta", "false")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
```

```javascript
import mql from '@microlink/mql'

const { data } = await mql('https://example.com', {

  data: {

    title: {

      selector: "h1",

      attr: "text"

    }

  },

  meta: false

})
```

Use `selector` for one element and `attr` for the value you want from it.

This is the best first step when you are learning a new page structure. Once the first field works, add the rest one by one.

## Extract a collection

If the page contains repeated elements, switch to `selectorAll`:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://news.ycombinator.com' URL with 'data' & 'meta' API parameters:

### CLI Microlink API example

```bash
microlink https://news.ycombinator.com&data.titles.selectorAll='.titleline > a'&data.titles.attr=text
```

### cURL Microlink API example

```bash
curl -G "https://api.microlink.io" \
  -d "url=https://news.ycombinator.com" \
  -d "data.titles.selectorAll=.titleline%20%3E%20a" \
  -d "data.titles.attr=text" \
  -d "meta=false"
```

### JavaScript Microlink API example

```javascript
import mql from '@microlink/mql'

const { data } = await mql('https://news.ycombinator.com', {
  data: {
    titles: {
      selectorAll: ".titleline > a",
      attr: "text"
    }
  },
  meta: false
})
```

### Python Microlink API example

```python
import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://news.ycombinator.com",
    "data.titles.selectorAll": ".titleline > a",
    "data.titles.attr": "text",
    "meta": "false"
}

response = requests.get(url, params=querystring)

print(response.json())
```

### Ruby Microlink API example

```ruby
require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://news.ycombinator.com",
  data.titles.selectorAll: ".titleline > a",
  data.titles.attr: "text",
  meta: "false"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body
```

### PHP Microlink API example

```php
<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://news.ycombinator.com",
    "data.titles.selectorAll" => ".titleline > a",
    "data.titles.attr" => "text",
    "meta" => "false"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}
```

### Golang Microlink API example

```
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    q := u.Query()
    q.Set("url", "https://news.ycombinator.com")
    q.Set("data.titles.selectorAll", ".titleline > a")
    q.Set("data.titles.attr", "text")
    q.Set("meta", "false")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
```

```javascript
import mql from '@microlink/mql'

const { data } = await mql('https://news.ycombinator.com', {

  data: {

    titles: {

      selectorAll: ".titleline > a",

      attr: "text"

    }

  },

  meta: false

})
```

Use `selectorAll` when you need an array instead of only the first match.

This pattern is ideal for headlines, product cards, search results, table rows, and navigation links.

## Return structured objects

You can group related values into one field by using nested `attr` rules:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://news.ycombinator.com' URL with 'data' & 'meta' API parameters:

### CLI Microlink API example

```bash
microlink https://news.ycombinator.com&data.stories.selectorAll=.athing&data.stories.attr.title.selector='.titleline > a'&data.stories.attr.title.attr=text&data.stories.attr.href.selector='.titleline > a'&data.stories.attr.href.attr=href&data.stories.attr.href.type=url
```

### cURL Microlink API example

```bash
curl -G "https://api.microlink.io" \
  -d "url=https://news.ycombinator.com" \
  -d "data.stories.selectorAll=.athing" \
  -d "data.stories.attr.title.selector=.titleline%20%3E%20a" \
  -d "data.stories.attr.title.attr=text" \
  -d "data.stories.attr.href.selector=.titleline%20%3E%20a" \
  -d "data.stories.attr.href.attr=href" \
  -d "data.stories.attr.href.type=url" \
  -d "meta=false"
```

### JavaScript Microlink API example

```javascript
import mql from '@microlink/mql'

const { data } = await mql('https://news.ycombinator.com', {
  data: {
    stories: {
      selectorAll: ".athing",
      attr: {
        title: {
          selector: ".titleline > a",
          attr: "text"
        },
        href: {
          selector: ".titleline > a",
          attr: "href",
          type: "url"
        }
      }
    }
  },
  meta: false
})
```

### Python Microlink API example

```python
import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://news.ycombinator.com",
    "data.stories.selectorAll": ".athing",
    "data.stories.attr.title.selector": ".titleline > a",
    "data.stories.attr.title.attr": "text",
    "data.stories.attr.href.selector": ".titleline > a",
    "data.stories.attr.href.attr": "href",
    "data.stories.attr.href.type": "url",
    "meta": "false"
}

response = requests.get(url, params=querystring)

print(response.json())
```

### Ruby Microlink API example

```ruby
require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://news.ycombinator.com",
  data.stories.selectorAll: ".athing",
  data.stories.attr.title.selector: ".titleline > a",
  data.stories.attr.title.attr: "text",
  data.stories.attr.href.selector: ".titleline > a",
  data.stories.attr.href.attr: "href",
  data.stories.attr.href.type: "url",
  meta: "false"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body
```

### PHP Microlink API example

```php
<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://news.ycombinator.com",
    "data.stories.selectorAll" => ".athing",
    "data.stories.attr.title.selector" => ".titleline > a",
    "data.stories.attr.title.attr" => "text",
    "data.stories.attr.href.selector" => ".titleline > a",
    "data.stories.attr.href.attr" => "href",
    "data.stories.attr.href.type" => "url",
    "meta" => "false"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}
```

### Golang Microlink API example

```
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    q := u.Query()
    q.Set("url", "https://news.ycombinator.com")
    q.Set("data.stories.selectorAll", ".athing")
    q.Set("data.stories.attr.title.selector", ".titleline > a")
    q.Set("data.stories.attr.title.attr", "text")
    q.Set("data.stories.attr.href.selector", ".titleline > a")
    q.Set("data.stories.attr.href.attr", "href")
    q.Set("data.stories.attr.href.type", "url")
    q.Set("meta", "false")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
```

```javascript
import mql from '@microlink/mql'

const { data } = await mql('https://news.ycombinator.com', {

  data: {

    stories: {

      selectorAll: ".athing",

      attr: {

        title: {

          selector: ".titleline > a",

          attr: "text"

        },

        href: {

          selector: ".titleline > a",

          attr: "href",

          type: "url"

        }

      }

    }

  },

  meta: false

})
```

Nested rules let each matched item become a structured object instead of a single string.

Use this when a card, row, or result item contains multiple related fields that should stay together.

## Use fallback rules

When the page structure is not consistent, provide more than one rule in priority order:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://example.com' URL with 'data' & 'meta' API parameters:

### CLI Microlink API example

```bash
microlink https://example.com&data.title='[object Object],[object Object],[object Object]'
```

### cURL Microlink API example

```bash
curl -G "https://api.microlink.io" \
  -d "url=https://example.com" \
  -d "data.title=%5Bobject%20Object%5D%2C%5Bobject%20Object%5D%2C%5Bobject%20Object%5D" \
  -d "meta=false"
```

### JavaScript Microlink API example

```javascript
import mql from '@microlink/mql'

const { data } = await mql('https://example.com', {
  data: {
    title: [
      {
        selector: 'meta[property="og:title"]',
        attr: "content"
      },
      {
        selector: "title",
        attr: "text"
      },
      {
        selector: "h1",
        attr: "text"
      }
    ]
  },
  meta: false
})
```

### Python Microlink API example

```python
import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://example.com",
    "data.title": "[object Object],[object Object],[object Object]",
    "meta": "false"
}

response = requests.get(url, params=querystring)

print(response.json())
```

### Ruby Microlink API example

```ruby
require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://example.com",
  data.title: "[object Object],[object Object],[object Object]",
  meta: "false"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body
```

### PHP Microlink API example

```php
<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://example.com",
    "data.title" => "[object Object],[object Object],[object Object]",
    "meta" => "false"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}
```

### Golang Microlink API example

```
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    q := u.Query()
    q.Set("url", "https://example.com")
    q.Set("data.title", "[object Object],[object Object],[object Object]")
    q.Set("meta", "false")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
```

```javascript
import mql from '@microlink/mql'

const { data } = await mql('https://example.com', {

  data: {

    title: [

      {

        selector: 'meta[property="og:title"]',

        attr: "content"

      },

      {

        selector: "title",

        attr: "text"

      },

      {

        selector: "h1",

        attr: "text"

      }

    ]

  },

  meta: false

})
```

Microlink tries each rule in order and keeps the first one that returns a valid value.

Fallbacks are especially useful across publisher templates, ecommerce catalogs, or documentation sites where the markup changes from page to page.

## Pick the right output form

`attr` and `type` solve different problems:

| Property | Use it for                                                                                        |
| -------- | ------------------------------------------------------------------------------------------------- |
| `attr`   | Choosing the source value such as `text`, `html`, `markdown`, `json`, `href`, `src`, or `content` |
| `type`   | Validating or normalizing the result as `url`, `number`, `date`, `image`, and more                |

For example, a link field usually needs both:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://example.com' URL with 'data' & 'meta' API parameters:

### CLI Microlink API example

```bash
microlink https://example.com&data.link.selector=a&data.link.attr=href&data.link.type=url
```

### cURL Microlink API example

```bash
curl -G "https://api.microlink.io" \
  -d "url=https://example.com" \
  -d "data.link.selector=a" \
  -d "data.link.attr=href" \
  -d "data.link.type=url" \
  -d "meta=false"
```

### JavaScript Microlink API example

```javascript
import mql from '@microlink/mql'

const { data } = await mql('https://example.com', {
  data: {
    link: {
      selector: "a",
      attr: "href",
      type: "url"
    }
  },
  meta: false
})
```

### Python Microlink API example

```python
import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://example.com",
    "data.link.selector": "a",
    "data.link.attr": "href",
    "data.link.type": "url",
    "meta": "false"
}

response = requests.get(url, params=querystring)

print(response.json())
```

### Ruby Microlink API example

```ruby
require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://example.com",
  data.link.selector: "a",
  data.link.attr: "href",
  data.link.type: "url",
  meta: "false"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body
```

### PHP Microlink API example

```php
<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://example.com",
    "data.link.selector" => "a",
    "data.link.attr" => "href",
    "data.link.type" => "url",
    "meta" => "false"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}
```

### Golang Microlink API example

```
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    q := u.Query()
    q.Set("url", "https://example.com")
    q.Set("data.link.selector", "a")
    q.Set("data.link.attr", "href")
    q.Set("data.link.type", "url")
    q.Set("meta", "false")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
```

```javascript
import mql from '@microlink/mql'

const { data } = await mql('https://example.com', {

  data: {

    link: {

      selector: "a",

      attr: "href",

      type: "url"

    }

  },

  meta: false

})
```

Think of `attr` as “where to read from” and `type` as “what shape this value should have”.

If you specifically want HTML-to-Markdown serialization, see the [Markdown guide](https://microlink.io/docs/guides/markdown).

## Extract JSON

When the target URL returns JSON instead of HTML, use `attr: 'json'` to parse the response body into structured data:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://pokeapi.co/api/v2/pokemon' URL with 'meta' & 'data' API parameters:

### CLI Microlink API example

```bash
microlink https://pokeapi.co/api/v2/pokemon&data.content.attr=json
```

### cURL Microlink API example

```bash
curl -G "https://api.microlink.io" \
  -d "url=https://pokeapi.co/api/v2/pokemon" \
  -d "meta=false" \
  -d "data.content.attr=json"
```

### JavaScript Microlink API example

```javascript
import mql from '@microlink/mql'

const { data } = await mql('https://pokeapi.co/api/v2/pokemon', {
  meta: false,
  data: {
    content: {
      attr: "json"
    }
  }
})
```

### Python Microlink API example

```python
import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://pokeapi.co/api/v2/pokemon",
    "meta": "false",
    "data.content.attr": "json"
}

response = requests.get(url, params=querystring)

print(response.json())
```

### Ruby Microlink API example

```ruby
require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://pokeapi.co/api/v2/pokemon",
  meta: "false",
  data.content.attr: "json"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body
```

### PHP Microlink API example

```php
<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://pokeapi.co/api/v2/pokemon",
    "meta" => "false",
    "data.content.attr" => "json"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}
```

### Golang Microlink API example

```
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    q := u.Query()
    q.Set("url", "https://pokeapi.co/api/v2/pokemon")
    q.Set("meta", "false")
    q.Set("data.content.attr", "json")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
```

```javascript
import mql from '@microlink/mql'

const { data } = await mql('https://pokeapi.co/api/v2/pokemon', {

  meta: false,

  data: {

    content: {

      attr: "json"

    }

  }

})
```

Run the request and inspect `data.content`. The parsed JSON object is returned as structured data, not a string.

Unlike other `attr` values, `json` is **whole-page only** — it always operates on the entire response body. Do not combine it with `selector` or `selectorAll`.

Key behaviors:

- The field name you declare becomes the response key.
- `attr: 'json'` parses the body with `JSON.parse` and returns native structured data (objects, arrays, strings, numbers, booleans, or `null`).
- The original shape is preserved exactly — no URL rewriting, no array compaction, no value normalization.
- Strings that contain HTML-like content (e.g. `"<b>bold</b>"`) pass through unchanged — they are not interpreted as DOM elements.

Microlink tries two strategies depending on how the JSON arrives:

1.  **`<pre>` tag present** — when the response is browser-rendered, JSON is often wrapped in a `<pre>` element. Microlink extracts the inner HTML, decodes HTML entities, and parses the result.
2.  **Plain body text** — when no `<pre>` exists, Microlink reads the raw body text directly and parses it.

This means `attr: 'json'` works regardless of whether you use `prerender: true` or `prerender: false`.

| Need                                         | Best approach                                                                    |
| -------------------------------------------- | -------------------------------------------------------------------------------- |
| Consume a REST API or JSON endpoint          | `attr: 'json'` on the endpoint URL                                               |
| Combine JSON data with HTML-extracted fields | Mix `attr: 'json'` (no selector) with other `data` rules that use selectors      |
| Parse a page that returns `application/json` | `attr: 'json'` handles it whether the body is raw or wrapped in `<pre>`          |
| Extract structured data from an HTML page    | Use `selector` + other `attr` values — `json` is not designed for HTML documents |

For delivery options (`embed`, `filter`, caching, and private endpoint handling), the same patterns from [delivery and response shaping](https://microlink.io/docs/guides/data-extraction/delivery-and-response) apply. A common production setup for JSON proxying:

```js
{

  url: 'https://pokeapi.co/api/v2/pokemon',

  data: {

    content: {

      attr: 'json'

    }

  },

  meta: false,

  prerender: false,

  ttl: '1d',

  staleTtl: 0

}
```

## Use evaluate for custom values

If selectors are still not enough, `evaluate` can compute a field directly in the browser context:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://example.com' URL with 'data' & 'meta' API parameters:

### CLI Microlink API example

```bash
microlink https://example.com&data.summary.evaluate='`${document.querySelector('"'"'h1'"'"')?.textContent.trim()} — ${document.querySelector('"'"'p'"'"')?.textContent.trim()}`'&data.summary.type=string
```

### cURL Microlink API example

```bash
curl -G "https://api.microlink.io" \
  -d "url=https://example.com" \
  -d "data.summary.evaluate=%60%24%7Bdocument.querySelector('h1')%3F.textContent.trim()%7D%20%E2%80%94%20%24%7Bdocument.querySelector('p')%3F.textContent.trim()%7D%60" \
  -d "data.summary.type=string" \
  -d "meta=false"
```

### JavaScript Microlink API example

```javascript
import mql from '@microlink/mql'

const { data } = await mql('https://example.com', {
  data: {
    summary: {
      evaluate: "`${document.querySelector('h1')?.textContent.trim()} — ${document.querySelector('p')?.textContent.trim()}`",
      type: "string"
    }
  },
  meta: false
})
```

### Python Microlink API example

```python
import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://example.com",
    "data.summary.evaluate": '''`${document.querySelector('h1')?.textContent.trim()} — ${document.querySelector('p')?.textContent.trim()}`''',
    "data.summary.type": "string",
    "meta": "false"
}

response = requests.get(url, params=querystring)

print(response.json())
```

### Ruby Microlink API example

```ruby
require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://example.com",
  data.summary.evaluate: "`${document.querySelector('h1')?.textContent.trim()} — ${document.querySelector('p')?.textContent.trim()}`",
  data.summary.type: "string",
  meta: "false"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body
```

### PHP Microlink API example

```php
<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://example.com",
    "data.summary.evaluate" => "`${document.querySelector('h1')?.textContent.trim()} — ${document.querySelector('p')?.textContent.trim()}`",
    "data.summary.type" => "string",
    "meta" => "false"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}
```

### Golang Microlink API example

```
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    data.summary.evaluateParam := ``${document.querySelector('h1')?.textContent.trim()} — ${document.querySelector('p')?.textContent.trim()}``

    q := u.Query()
    q.Set("url", "https://example.com")
    q.Set("data.summary.evaluate", data.summary.evaluateParam)
    q.Set("data.summary.type", "string")
    q.Set("meta", "false")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
```

```javascript
import mql from '@microlink/mql'

const { data } = await mql('https://example.com', {

  data: {

    summary: {

      evaluate: "`${document.querySelector('h1')?.textContent.trim()} — ${document.querySelector('p')?.textContent.trim()}`",

      type: "string"

    }

  },

  meta: false

})
```

Use `evaluate` for values that are awkward to express with selectors alone, but keep it as a last resort.

Start with plain selectors and fallbacks. Add `evaluate` only when the page needs custom logic.

## Rule references

For the full rule surface, see the MQL reference pages for [selector](https://microlink.io/docs/mql/data/selector), [selectorAll](https://microlink.io/docs/mql/data/selectorAll), [attr](https://microlink.io/docs/mql/data/attr), [type](https://microlink.io/docs/mql/data/type), [evaluate](https://microlink.io/docs/mql/data/evaluate), [nested rules](https://microlink.io/docs/mql/rules/nested), and [fallback rules](https://microlink.io/docs/mql/rules/fallbacks).

## Next step

Learn how to render the right page state before extraction in [page preparation](https://microlink.io/docs/guides/data-extraction/page-preparation).

Last updated on April 13, 2026

[Edit on GitHub](https://github.com/microlinkhq/www/blob/master/src/content/docs/guides/data-extraction/defining-rules.md)