Skip to content

Proxy

These proxy patterns apply to every Microlink workflow: screenshots, PDFs, data extraction, metadata, and insights. Use them whenever a target site blocks headless browsers, enforces rate limits on a specific IP, or geofences content by region.

When you need a proxy

Not every site needs one. Use a proxy when you encounter:
SignalWhat is happening
EPROXYNEEDED error codeThe API detected blocking and the request cannot succeed without a proxy
Empty or partial results on a known-good URLThe target is returning a CAPTCHA or an antibot challenge page
Works locally but not via the APIYour origin IP is blocked or throttled by the target
Content differs by regionThe target serves different content based on geographic IP

Automatic proxy
PRO

Every
PRO
plan includes automatic proxy resolution — you do not need to supply a proxy URL. When Microlink detects that a site requires a proxy to fetch correctly, it routes the request through a rotating proxy pool automatically.
Microlink identifies the specific antibot provider blocking your request and routes it through a dedicated resolution path. For most sites, the Pro plan handles this automatically. We ensure performance across the Top 500 most popular websites worldwide.
You can confirm automatic proxy was used by checking the x-fetch-mode response header. Any value prefixed with proxy- means a proxy was active:
x-fetch-mode: prerender-proxy

Bring your own proxy
PRO

If you have a dedicated proxy service — for example a residential proxy with a specific country IP — pass the proxy URL using the proxy parameter:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://geolocation.microlink.io' URL with 'proxy' API parameter:

CLI Microlink API example

microlink https://geolocation.microlink.io&proxy=https://myproxy:[email protected]:8001

cURL Microlink API example

curl -G "https://api.microlink.io" \
  -d "url=https://geolocation.microlink.io" \
  -d "proxy=https://myproxy:[email protected]:8001"

JavaScript Microlink API example

import mql from '@microlink/mql'

const { data } = await mql('https://geolocation.microlink.io', {
  proxy: "https://myproxy:[email protected]:8001"
})

Python Microlink API example

import requests

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

querystring = {
    "url": "https://geolocation.microlink.io",
    "proxy": "https://myproxy:[email protected]:8001"
}

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

print(response.json())

Ruby Microlink API example

require 'uri'
require 'net/http'

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

params = {
  url: "https://geolocation.microlink.io",
  proxy: "https://myproxy:[email protected]:8001"
}

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

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

$params = [
    "url" => "https://geolocation.microlink.io",
    "proxy" => "https://myproxy:[email protected]:8001"
];

$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://geolocation.microlink.io")
    q.Set("proxy", "https://myproxy:[email protected]:8001")
    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))
}
The x-fetch-mode response header will be prefixed with proxy-* when the request routes through your proxy.
The proxy URL must be a valid . The supported format is:
https://username:password@hostname:port
All sub-requests made while resolving the target URL (redirects, assets, dynamic fetches) go through the same proxy server.

Verify proxy is active

Check these response headers to confirm a proxy was used:
HeaderExpected value
x-fetch-modeAny value starting with proxy- (e.g. prerender-proxy, fetch-proxy)
x-pricing-planpro — proxy requires a paid plan
x-cache-statusBYPASS on a fresh uncached request
A full response using a proxy looks like:
HTTP/2 200
content-type: application/json; charset=utf-8
x-response-time: 1.7s
x-pricing-plan: pro
x-fetch-mode: prerender-proxy
x-cache-ttl: 86400000
x-request-id: iad:2eb66538-0a16-4c56-b613-511d99507c9f
x-cache-status: BYPASS
cache-control: public, must-revalidate, max-age=0

Combine proxy with other parameters

Proxy works with every workflow parameter. Some useful combinations:

Screenshot through a proxy

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

CLI Microlink API example

microlink https://microlink.io&screenshot&proxy=https://myproxy:[email protected]:8001

cURL Microlink API example

curl -G "https://api.microlink.io" \
  -d "url=https://microlink.io" \
  -d "screenshot=true" \
  -d "meta=false" \
  -d "proxy=https://myproxy:[email protected]:8001"

JavaScript Microlink API example

import mql from '@microlink/mql'

const { data } = await mql('https://microlink.io', {
  screenshot: true,
  meta: false,
  proxy: "https://myproxy:[email protected]:8001"
})

Python Microlink API example

import requests

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

querystring = {
    "url": "https://microlink.io",
    "screenshot": "true",
    "meta": "false",
    "proxy": "https://myproxy:[email protected]:8001"
}

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

print(response.json())

Ruby Microlink API example

require 'uri'
require 'net/http'

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

params = {
  url: "https://microlink.io",
  screenshot: "true",
  meta: "false",
  proxy: "https://myproxy:[email protected]:8001"
}

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

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

$params = [
    "url" => "https://microlink.io",
    "screenshot" => "true",
    "meta" => "false",
    "proxy" => "https://myproxy:[email protected]:8001"
];

$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://microlink.io")
    q.Set("screenshot", "true")
    q.Set("meta", "false")
    q.Set("proxy", "https://myproxy:[email protected]:8001")
    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))
}
Adding meta: false skips metadata extraction and focuses the request on the screenshot alone.

Data extraction through a proxy

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

CLI Microlink API example

microlink https://microlink.io&data.title.selector=h1&data.title.attr=text&proxy=https://myproxy:[email protected]:8001

cURL Microlink API example

curl -G "https://api.microlink.io" \
  -d "url=https://microlink.io" \
  -d "data.title.selector=h1" \
  -d "data.title.attr=text" \
  -d "proxy=https://myproxy:[email protected]:8001" \
  -d "meta=false"

JavaScript Microlink API example

import mql from '@microlink/mql'

const { data } = await mql('https://microlink.io', {
  data: {
    title: {
      selector: "h1",
      attr: "text"
    }
  },
  proxy: "https://myproxy:[email protected]:8001",
  meta: false
})

Python Microlink API example

import requests

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

querystring = {
    "url": "https://microlink.io",
    "data.title.selector": "h1",
    "data.title.attr": "text",
    "proxy": "https://myproxy:[email protected]:8001",
    "meta": "false"
}

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

print(response.json())

Ruby Microlink API example

require 'uri'
require 'net/http'

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

params = {
  url: "https://microlink.io",
  data.title.selector: "h1",
  data.title.attr: "text",
  proxy: "https://myproxy:[email protected]:8001",
  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

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

$params = [
    "url" => "https://microlink.io",
    "data.title.selector" => "h1",
    "data.title.attr" => "text",
    "proxy" => "https://myproxy:[email protected]:8001",
    "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://microlink.io")
    q.Set("data.title.selector", "h1")
    q.Set("data.title.attr", "text")
    q.Set("proxy", "https://myproxy:[email protected]:8001")
    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))
}
Pass custom extraction rules alongside a proxy when the target requires one to deliver content.

Proxy with retry for flaky targets

Some proxy endpoints are temporarily unreachable or the target site intermittently challenges requests. Combine proxy with retry to handle transient failures automatically:

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

CLI Microlink API example

microlink https://microlink.io&proxy=https://myproxy:[email protected]:8001&retry=3

cURL Microlink API example

curl -G "https://api.microlink.io" \
  -d "url=https://microlink.io" \
  -d "proxy=https://myproxy:[email protected]:8001" \
  -d "retry=3" \
  -d "meta=false"

JavaScript Microlink API example

import mql from '@microlink/mql'

const { data } = await mql('https://microlink.io', {
  proxy: "https://myproxy:[email protected]:8001",
  retry: 3,
  meta: false
})

Python Microlink API example

import requests

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

querystring = {
    "url": "https://microlink.io",
    "proxy": "https://myproxy:[email protected]:8001",
    "retry": "3",
    "meta": "false"
}

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

print(response.json())

Ruby Microlink API example

require 'uri'
require 'net/http'

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

params = {
  url: "https://microlink.io",
  proxy: "https://myproxy:[email protected]:8001",
  retry: "3",
  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

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

$params = [
    "url" => "https://microlink.io",
    "proxy" => "https://myproxy:[email protected]:8001",
    "retry" => "3",
    "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://microlink.io")
    q.Set("proxy", "https://myproxy:[email protected]:8001")
    q.Set("retry", "3")
    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))
}
Server-side retries with exponential backoff reduce failures from temporarily blocked or slow proxy connections.

Geolocation: Target region-specific content

A common use case is scraping a site that serves different content depending on the visitor's country. Route through a country-specific proxy IP to get the version you need:
import mql from '@microlink/mql'

const { data } = await mql('https://example.com/pricing', {
  proxy: 'https://user:[email protected]:8080',
  meta: false
})
Pair this with a reliable geolocation test URL to verify the proxy is resolving from the expected country before sending production requests:

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

CLI Microlink API example

microlink https://geolocation.microlink.io&proxy=https://myproxy:[email protected]:8001

cURL Microlink API example

curl -G "https://api.microlink.io" \
  -d "url=https://geolocation.microlink.io" \
  -d "proxy=https://myproxy:[email protected]:8001" \
  -d "meta=false"

JavaScript Microlink API example

import mql from '@microlink/mql'

const { data } = await mql('https://geolocation.microlink.io', {
  proxy: "https://myproxy:[email protected]:8001",
  meta: false
})

Python Microlink API example

import requests

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

querystring = {
    "url": "https://geolocation.microlink.io",
    "proxy": "https://myproxy:[email protected]:8001",
    "meta": "false"
}

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

print(response.json())

Ruby Microlink API example

require 'uri'
require 'net/http'

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

params = {
  url: "https://geolocation.microlink.io",
  proxy: "https://myproxy:[email protected]:8001",
  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

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

$params = [
    "url" => "https://geolocation.microlink.io",
    "proxy" => "https://myproxy:[email protected]:8001",
    "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://geolocation.microlink.io")
    q.Set("proxy", "https://myproxy:[email protected]:8001")
    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))
}
geolocation.microlink.io returns the origin IP and country seen by the server — useful to confirm a proxy is routing through the right region.

Keep proxy credentials secure

Proxy URLs contain credentials. Treat them the same as API keys:
  • Never embed them in client-side code, public HTML, or embed URLs.
  • Pass them from environment variables in server-side code:
import mql from '@microlink/mql'

const { data } = await mql('https://example.com', {
  proxy: process.env.PROXY_URL,
  meta: false
})

Error codes

ErrorCauseFix
EPROXYNEEDEDThe target requires a proxy but none was suppliedAdd proxy to the request or upgrade to a
PRO
plan for automatic proxy
EPROXYproxy parameter used without a
PRO
plan
Upgrade to a paid plan
EAUTHAPI key missing or invalidCheck your x-api-key header
EPROSent x-api-key to api.microlink.ioUse pro.microlink.io instead
See the full error codes reference and the proxy parameter reference for all supported values.

See also

  • Private pages — forward cookies, authorization headers, and other credentials to target pages.
  • Troubleshooting — fix timeouts, blocked sites, and auth errors across all workflows.
  • Production patterns — endpoint selection, retries, rate limits, and credential safety.