Insights: Troubleshooting
When an Insights result looks wrong, the cause is usually one of four things: the page rendered as a generic shell, the request did too much work, the wrong page variant was analyzed, or the site blocked browser automation.
Quick triage checklist
- Run one analysis at a time before you run both.
- If the result is missing or generic on a SPA, try
prerender: true. - If the request is too slow, remove fixed waits and unnecessary analysis first.
- If the wrong locale, region, or personalization is showing up, use
headersor forwarded auth headersPRO. - If the site blocks automation or geofences content, use
proxywith a proxy URLPRO.
The result is missing or generic
Start by forcing browser rendering:
The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://vercel.com' URL with 'insights', 'meta' & 'prerender' API parameters:
CLI Microlink API example
microlink https://vercel.com&insights.technologies&prerendercURL Microlink API example
curl -G "https://api.microlink.io" \
-d "url=https://vercel.com" \
-d "insights.technologies=true" \
-d "insights.lighthouse=false" \
-d "meta=false" \
-d "prerender=true"JavaScript Microlink API example
import createClient from 'microlink.io'
const microlink = createClient()
const technologies = await microlink.technologies('https://vercel.com', {
prerender: true
})Python Microlink API example
import requests
url = "https://api.microlink.io/"
querystring = {
"url": "https://vercel.com",
"insights.technologies": "true",
"insights.lighthouse": "false",
"meta": "false",
"prerender": "true"
}
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://vercel.com",
insights.technologies: "true",
insights.lighthouse: "false",
meta: "false",
prerender: "true"
}
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.bodyPHP Microlink API example
<?php
$baseUrl = "https://api.microlink.io/";
$params = [
"url" => "https://vercel.com",
"insights.technologies" => "true",
"insights.lighthouse" => "false",
"meta" => "false",
"prerender" => "true"
];
$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://vercel.com")
q.Set("insights.technologies", "true")
q.Set("insights.lighthouse", "false")
q.Set("meta", "false")
q.Set("prerender", "true")
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))
}import createClient from 'microlink.io'
const microlink = createClient()
const technologies = await microlink.technologies('https://vercel.com', {
prerender: true
})When the initial HTML is too generic,
prerender: true can expose the real page state before analysis runs.If the output is still wrong, switch to a single analysis and add
waitUntil plus waitForSelector for dynamic pages.The request is too slow or times out
If you hit
ETIMEOUT or EBRWSRTIMEOUT, reduce the amount of work before you simply raise timeout:The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://vercel.com' URL with 'insights', 'meta', 'retry' & 'timeout' API parameters:
CLI Microlink API example
microlink https://vercel.com&insights.lighthouse&retry=3&timeout=20scURL Microlink API example
curl -G "https://api.microlink.io" \
-d "url=https://vercel.com" \
-d "insights.technologies=false" \
-d "insights.lighthouse=true" \
-d "meta=false" \
-d "retry=3" \
-d "timeout=20s"JavaScript Microlink API example
import createClient from 'microlink.io'
const microlink = createClient()
const report = await microlink.lighthouse('https://vercel.com', {
retry: 3,
timeout: "20s"
})Python Microlink API example
import requests
url = "https://api.microlink.io/"
querystring = {
"url": "https://vercel.com",
"insights.technologies": "false",
"insights.lighthouse": "true",
"meta": "false",
"retry": "3",
"timeout": "20s"
}
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://vercel.com",
insights.technologies: "false",
insights.lighthouse: "true",
meta: "false",
retry: "3",
timeout: "20s"
}
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.bodyPHP Microlink API example
<?php
$baseUrl = "https://api.microlink.io/";
$params = [
"url" => "https://vercel.com",
"insights.technologies" => "false",
"insights.lighthouse" => "true",
"meta" => "false",
"retry" => "3",
"timeout" => "20s"
];
$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://vercel.com")
q.Set("insights.technologies", "false")
q.Set("insights.lighthouse", "true")
q.Set("meta", "false")
q.Set("retry", "3")
q.Set("timeout", "20s")
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))
}import createClient from 'microlink.io'
const microlink = createClient()
const report = await microlink.lighthouse('https://vercel.com', {
retry: 3,
timeout: "20s"
})Increase timeout only after removing unnecessary analysis and rendering work.
The most effective fixes are:
- run only technologies or only Lighthouse, not both
- set
meta: falsewhen the standard metadata payload is not needed - use
filter: 'insights'when you only need the Insights payload - use
prerender: falseif the page already exposes enough information in HTML - replace
waitForTimeoutwithwaitForSelector - disable
javascriptwhen the page does not need it - add
ttlorstaleTtlPROfor repeated runs
Private pages and blocked sites PRO
If the page only works for logged-in users, a specific locale, or a particular request context:
- use
headersfor non-sensitive request shaping - use
x-api-header-*for cookies or authorization - use
pro.microlink.iowhen sendingx-api-key
Some sites block headless browsers, require a region-specific IP, or trigger antibot protection. In those cases, use
proxy:The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://example.com' URL with 'insights', 'meta', 'proxy' & 'apiKey' API parameters:
CLI Microlink API example
microlink https://example.com&insights.technologies&proxy.url=https://myproxy:[email protected]:8001 --api-key YOUR_API_TOKENcURL Microlink API example
curl -G "https://pro.microlink.io" \
-H "x-api-key: YOUR_API_TOKEN" \
-d "url=https://example.com" \
-d "insights.technologies=true" \
-d "insights.lighthouse=false" \
-d "meta=false" \
-d "proxy.url=https://myproxy:[email protected]:8001"JavaScript Microlink API example
import createClient from 'microlink.io'
const microlink = createClient({ apiKey: "YOUR_API_TOKEN" })
const technologies = await microlink.technologies('https://example.com', {
proxy: {
url: "https://myproxy:[email protected]:8001"
}
})Python Microlink API example
import requests
url = "https://pro.microlink.io/"
querystring = {
"url": "https://example.com",
"insights.technologies": "true",
"insights.lighthouse": "false",
"meta": "false",
"proxy.url": "https://myproxy:[email protected]:8001"
}
headers = {
"x-api-key": "YOUR_API_TOKEN"
}
response = requests.get(url, params=querystring, headers=headers)
print(response.json())Ruby Microlink API example
require 'uri'
require 'net/http'
base_url = "https://pro.microlink.io/"
params = {
url: "https://example.com",
insights.technologies: "true",
insights.lighthouse: "false",
meta: "false",
proxy.url: "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)
request['x-api-key'] = "YOUR_API_TOKEN"
response = http.request(request)
puts response.bodyPHP Microlink API example
<?php
$baseUrl = "https://pro.microlink.io/";
$params = [
"url" => "https://example.com",
"insights.technologies" => "true",
"insights.lighthouse" => "false",
"meta" => "false",
"proxy.url" => "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",
CURLOPT_HTTPHEADER => [
"x-api-key: YOUR_API_TOKEN"
]
]);
$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://pro.microlink.io"
u, err := url.Parse(baseURL)
if err != nil {
panic(err)
}
q := u.Query()
q.Set("url", "https://example.com")
q.Set("insights.technologies", "true")
q.Set("insights.lighthouse", "false")
q.Set("meta", "false")
q.Set("proxy.url", "https://myproxy:[email protected]:8001")
u.RawQuery = q.Encode()
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
panic(err)
}
req.Header.Set("x-api-key", "YOUR_API_TOKEN")
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))
}import createClient from 'microlink.io'
const microlink = createClient({ apiKey: "YOUR_API_TOKEN" })
const technologies = await microlink.technologies('https://example.com', {
proxy: {
url: "https://myproxy:[email protected]:8001"
}
})Use a proxy URL when the target site blocks headless traffic, geofences content, or rate-limits your origin.
If the API returns
EPROXYNEEDED, that is the clearest signal that the target site needs a proxy-backed request.Auth and plan errors
Some common errors point directly to setup issues:
EAUTH— the API key is missing or invalid.EPRO— you sentx-api-keytoapi.microlink.ioinstead ofpro.microlink.io.EHEADERS—headersrequires aPROplan.EPROXY—proxyrequires aPROplan.ETTLorESTTL— configurable cache parameters require aPROplan.ERATE— you reached the free-tier or plan quota limit.
Useful headers while debugging
Open the response headers view in the interactive editor and look for:
x-cache-status— whether the response was aMISS,HIT, orBYPASSx-cache-ttl— the effective cache lifetimex-fetch-mode— whether the request was fetched, prerendered, or proxy-backedx-fetch-time— time spent fetching and renderingx-pricing-plan— whether the request ran on the free or Pro planx-response-time— the total request duration
These headers usually tell you whether the problem is caching, rendering, auth, or target-site protection.
Next step
See the guides overview for the rest of the Microlink guide set.