Reports
Analyse a page, read the findings, and look one up by URL.
Reports are the core of the API: submit a URL, get back the analysis. A page that has been analysed recently returns immediately from cache; one that has not is queued, and you poll for it.
A cached report does not spend your report allowance. Re-reading an analysis costs us nothing, so charging for it would make the cache feel like a penalty.
POST /reports
Analyse a page
Submits a URL. Returns 200 with the report when one is already cached, or 202 when it has been queued.
Body fields
| Name | Type | Notes | |
|---|---|---|---|
url | string | required | The page to analyse. Must be http or https and publicly reachable. |
render | boolean | optional | Run the page in a browser first. Slower, and only useful for a page whose content is built by JavaScript. |
Request
curl -X POST "https://webrankpage.com/api/v1/reports" \
-H "Authorization: Bearer wrp_live_8fKp2mQx9tR4vN7c" \
-H "Content-Type: application/json" \
-d '{"url": "https://onbixo.com/pricing"}'<?php
$ch = curl_init('https://webrankpage.com/api/v1/reports');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer wrp_live_8fKp2mQx9tR4vN7c',
'Content-Type: application/json',
],
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => json_encode([
'url' => 'https://onbixo.com/pricing',
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($response);// Node 18+, or any server-side runtime. Never in browser code:
// an API key in a page is readable by anyone who opens it.
const response = await fetch('https://webrankpage.com/api/v1/reports', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.WEBRANKPAGE_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({"url": "https://onbixo.com/pricing"}),
});
const data = await response.json();
console.log(data);import requests
response = requests.post(
'https://webrankpage.com/api/v1/reports',
headers={'Authorization': 'Bearer wrp_live_8fKp2mQx9tR4vN7c'},
json={'url': 'https://onbixo.com/pricing'},
)
print(response.json())require 'net/http'
require 'json'
uri = URI('https://webrankpage.com/api/v1/reports')
request = Net::HTTP::Post.new(uri)
request['Authorization'] = 'Bearer wrp_live_8fKp2mQx9tR4vN7c'
request['Content-Type'] = 'application/json'
request.body = { 'url' => 'https://onbixo.com/pricing' }.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
puts JSON.parse(response.body)package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
func main() {
body := bytes.NewBufferString(`{"url": "https://onbixo.com/pricing"}`)
req, _ := http.NewRequest("POST", "https://webrankpage.com/api/v1/reports", body)
req.Header.Set("Authorization", "Bearer wrp_live_8fKp2mQx9tR4vN7c")
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var data map[string]interface{}
json.NewDecoder(res.Body).Decode(&data)
fmt.Println(data)
}Response
{
"status": "queued",
"key": "gb4Z0oltSmwy",
"url": "https://onbixo.com/pricing",
"poll": "https://webrankpage.com/api/v1/reports/gb4Z0oltSmwy"
}On 202, poll the poll URL every few seconds. Most analyses finish in under thirty seconds; a slow site can take longer.
GET /reports/{key}
Read one report
Returns the full analysis, including every finding with its evidence and what to do about it. While an analysis is still running this returns 202 and a status rather than a 404.
Request
curl "https://webrankpage.com/api/v1/reports/gb4Z0oltSmwy" \
-H "Authorization: Bearer wrp_live_8fKp2mQx9tR4vN7c"<?php
$ch = curl_init('https://webrankpage.com/api/v1/reports/gb4Z0oltSmwy');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer wrp_live_8fKp2mQx9tR4vN7c',
],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($response);// Node 18+, or any server-side runtime. Never in browser code:
// an API key in a page is readable by anyone who opens it.
const response = await fetch('https://webrankpage.com/api/v1/reports/gb4Z0oltSmwy', {
headers: {
Authorization: `Bearer ${process.env.WEBRANKPAGE_KEY}`,
},
});
const data = await response.json();
console.log(data);import requests
response = requests.get(
'https://webrankpage.com/api/v1/reports/gb4Z0oltSmwy',
headers={'Authorization': 'Bearer wrp_live_8fKp2mQx9tR4vN7c'},
)
print(response.json())require 'net/http'
require 'json'
uri = URI('https://webrankpage.com/api/v1/reports/gb4Z0oltSmwy')
request = Net::HTTP::Get.new(uri)
request['Authorization'] = 'Bearer wrp_live_8fKp2mQx9tR4vN7c'
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
puts JSON.parse(response.body)package main
import (
"encoding/json"
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://webrankpage.com/api/v1/reports/gb4Z0oltSmwy", nil)
req.Header.Set("Authorization", "Bearer wrp_live_8fKp2mQx9tR4vN7c")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var data map[string]interface{}
json.NewDecoder(res.Body).Decode(&data)
fmt.Println(data)
}Response
{
"report": {
"status": "complete",
"key": "xRqeRgaHlR4i",
"url": "https://onbixo.com/pricing",
"title": "Pricing - Onbixo",
"score": 86,
"grade": "A",
"word_count": 1342,
"issues": {
"critical": 1,
"recommended": 8,
"optional": 2,
"passed": 52
},
"findings": [
{
"check": "title.length",
"severity": "recommended",
"result": "warn",
"message": "The title is only 16 characters; there is room for more descriptive wording (50 to 60 recommended).",
"evidence": "Pricing - Onbixo",
"remediation": null,
"impact": 2,
"effort": 2
},
{
"check": "description.length",
"severity": "recommended",
"result": "warn",
"message": "The meta description is 214 characters and will likely be truncated.",
"evidence": "Simple, flat-rate pricing for Onbixo - Free, Starter ($39), Growth ($79), Team ($149) and Scale ($299). Every tier is MAU-capped with a graceful block, never a surprise overage bill. No sales call, cancel any time.",
"remediation": null,
"impact": 3,
"effort": 1
truncated. The full response continues.
GET /reports
List reports in this workspace
Everything this workspace has analysed, newest first.
Query parameters
| Name | Type | Notes | |
|---|---|---|---|
limit | integer | optional | 1 to 100. Defaults to 25. |
offset | integer | optional | How many to skip. |
host | string | optional | Only pages on this hostname. |
Request
curl "https://webrankpage.com/api/v1/reports" \
-H "Authorization: Bearer wrp_live_8fKp2mQx9tR4vN7c"<?php
$ch = curl_init('https://webrankpage.com/api/v1/reports');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer wrp_live_8fKp2mQx9tR4vN7c',
],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($response);// Node 18+, or any server-side runtime. Never in browser code:
// an API key in a page is readable by anyone who opens it.
const response = await fetch('https://webrankpage.com/api/v1/reports', {
headers: {
Authorization: `Bearer ${process.env.WEBRANKPAGE_KEY}`,
},
});
const data = await response.json();
console.log(data);import requests
response = requests.get(
'https://webrankpage.com/api/v1/reports',
headers={'Authorization': 'Bearer wrp_live_8fKp2mQx9tR4vN7c'},
)
print(response.json())require 'net/http'
require 'json'
uri = URI('https://webrankpage.com/api/v1/reports')
request = Net::HTTP::Get.new(uri)
request['Authorization'] = 'Bearer wrp_live_8fKp2mQx9tR4vN7c'
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
puts JSON.parse(response.body)package main
import (
"encoding/json"
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://webrankpage.com/api/v1/reports", nil)
req.Header.Set("Authorization", "Bearer wrp_live_8fKp2mQx9tR4vN7c")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var data map[string]interface{}
json.NewDecoder(res.Body).Decode(&data)
fmt.Println(data)
}Response
{
"reports": [
{
"key": "xRqeRgaHlR4i",
"url": "https://onbixo.com/pricing",
"host": "onbixo.com",
"title": "Pricing - Onbixo",
"score": 86,
"grade": "A",
"issues": {
"critical": 1,
"recommended": 8,
"optional": 2
},
"first_run_at": "2026-09-24T06:14:16+00:00",
"last_run_at": "2026-09-24T06:14:16+00:00",
"run_count": 1
},
{
"key": "_Eg_N3L5kzik",
"url": "https://onbixo.com/blog",
"host": "onbixo.com",
"title": "Blog - Onbixo",
"score": 89,
"grade": "A",
"issues": {
"critical": 0,
"recommended": 10,
"optional": 2
},
truncated. The full response continues.
GET /reports/lookup
Find a report by URL
When you have the address but not the key. Returns the most recent analysis of that exact URL, or 404 if it has never been analysed.
Query parameters
| Name | Type | Notes | |
|---|---|---|---|
url | string | required | The full URL, encoded. |
Request
curl "https://webrankpage.com/api/v1/reports/lookup" \
-H "Authorization: Bearer wrp_live_8fKp2mQx9tR4vN7c"<?php
$ch = curl_init('https://webrankpage.com/api/v1/reports/lookup');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer wrp_live_8fKp2mQx9tR4vN7c',
],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($response);// Node 18+, or any server-side runtime. Never in browser code:
// an API key in a page is readable by anyone who opens it.
const response = await fetch('https://webrankpage.com/api/v1/reports/lookup', {
headers: {
Authorization: `Bearer ${process.env.WEBRANKPAGE_KEY}`,
},
});
const data = await response.json();
console.log(data);import requests
response = requests.get(
'https://webrankpage.com/api/v1/reports/lookup',
headers={'Authorization': 'Bearer wrp_live_8fKp2mQx9tR4vN7c'},
)
print(response.json())require 'net/http'
require 'json'
uri = URI('https://webrankpage.com/api/v1/reports/lookup')
request = Net::HTTP::Get.new(uri)
request['Authorization'] = 'Bearer wrp_live_8fKp2mQx9tR4vN7c'
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
puts JSON.parse(response.body)package main
import (
"encoding/json"
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://webrankpage.com/api/v1/reports/lookup", nil)
req.Header.Set("Authorization", "Bearer wrp_live_8fKp2mQx9tR4vN7c")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var data map[string]interface{}
json.NewDecoder(res.Body).Decode(&data)
fmt.Println(data)
}Response
{
"report": {
"key": "xRqeRgaHlR4i",
"url": "https://onbixo.com/pricing",
"score": 86,
"grade": "A",
"last_run_at": "2026-09-25T04:38:11+00:00"
}
}