Skip to main content

Report API

The public v2 Report API returns urlquery analysis reports, their screenshots, and captured resources. It also lists recent and related reports and searches historical reports.

All routes are on https://api.urlquery.net and require x-apikey. Every result is filtered by what your API key may see, as described in report visibility.

MethodPathQuota classResult
GET/public/v2/reports/{report_id}/overviewreport_lookupCompact report overview.
GET/public/v2/reports/{report_id}report_lookupFull report document.
GET/public/v2/reports/{report_id}/screenshotreport_lookupScreenshot image (PNG).
GET/public/v2/reports/{report_id}/resources/{hash}/contentreport_lookupCaptured resource from the report, as a download.
DELETE/public/v2/reports/{report_id}report_lookupDelete a report you own.
GET/public/v2/reports/recentreport_collectionRecent reports, newest first.
GET/public/v2/reports/relatedreport_collectionRecent public reports for the same target IP address, ASN, or domain.
GET/public/v2/reports/searchreport_searchSearch historical reports.

Every call also consumes the account's overall v2 quota.

Interpretation​

  • Reports describe what the analysis environment observed when it visited a URL. They are evidence for an investigation, not a verdict on their own. See reports and evidence.
  • Lists and search results contain only reports your key may see. A report you cannot see returns 404 NOT_FOUND, the same as a report that does not exist.
  • Captured content comes from potentially malicious sites. Store and inspect screenshots and resources only in an isolated environment.

Get a report​

GET /public/v2/reports/{report_id}/overview
GET /public/v2/reports/{report_id}

report_id is a UUID. Start with the overview, and request the full report only when you need its evidence.

curl --fail-with-body \
--header "x-apikey: ${URLQUERY_API_KEY}" \
"https://api.urlquery.net/public/v2/reports/<REPORT_ID>/overview"
{
"success": true,
"data": {
"report_id": "<REPORT_ID>",
"status": "done",
"date": "2026-10-01T12:00:00Z",
"tags": ["phishing"],
"url": {"schema": "https", "addr": "example.com/login", "fqdn": "example.com", "domain": "example.com", "tld": "com"},
"ip": {"addr": "192.0.2.10", "port": 443, "asn": 64500, "as": "Example AS", "country": "Norway", "country_code": "NO"},
"final": {"url": {"schema": "https", "addr": "example.com/login", "fqdn": "example.com", "domain": "example.com", "tld": "com"}, "title": "Sign in"},
"access": "public",
"alert_count": {"ids": 0, "urlquery": 2, "analyzer": 1},
"hosts": [
{
"fqdn": "example.com",
"ip": {"addr": "192.0.2.10", "port": 443, "asn": 64500, "as": "Example AS", "country": "Norway", "country_code": "NO"},
"domain_registered": "2026-09-28",
"domain_rank": 0,
"first_seen": "2026-09-29T08:00:00Z",
"last_seen": "2026-10-01T12:00:00Z",
"request_count": 14,
"alert_count": 3,
"sent_data": 2048,
"received_data": 512000,
"technologies": ["nginx", "PHP"]
}
]
}
}

hosts lists every host the analysis contacted, with its IP and network, popularity rank (0 when unranked), registration date and passive DNS bounds when known, traffic and alert counts, and fingerprinted technologies. Lists and search results carry the same hosts, so you can group a set of reports by infrastructure without fetching each full report.

The full report is the stored report document. It has the overview's identity, URL, IP, final page, and tag fields at the top level, and adds HTTP transactions (http), JavaScript, detections, extracted artifacts, and submission details (submit, settings). Three overview fields sit elsewhere: visibility is settings.access, alert counts are stats.alert_count, and the hosts are summary, with technology details under fingerprints. New fields can be added over time; ignore fields you do not recognize.

Get report evidence​

GET /public/v2/reports/{report_id}/screenshot
GET /public/v2/reports/{report_id}/resources/{hash}/content

The screenshot is returned as image/png. Resource content is returned as application/octet-stream with Content-Disposition: attachment, whatever its original type, so browsers do not render it. Both are sent with Cache-Control: private, no-store and X-Content-Type-Options: nosniff.

hash is the MD5, SHA-1, SHA-256, or SHA-512 of the resource, in hexadecimal. The resource must have been captured in that report, and you must be able to see the report. Find hashes in the full report, for example in the HTTP transactions.

curl --fail-with-body \
--header "x-apikey: ${URLQUERY_API_KEY}" \
--output resource.bin \
"https://api.urlquery.net/public/v2/reports/<REPORT_ID>/resources/<SHA256>/content"

Errors from these routes still use the JSON error envelope.

Delete a report​

DELETE /public/v2/reports/{report_id}

Only the account that submitted a report can delete it. The response is 200 OK with an empty data object. For any other report, the response is 404 NOT_FOUND and nothing changes.

curl --fail-with-body --request DELETE \
--header "x-apikey: ${URLQUERY_API_KEY}" \
"https://api.urlquery.net/public/v2/reports/<REPORT_ID>"

List recent reports​

GET /public/v2/reports/recent
ParameterValues
scopeall (default): your own reports and reports open to your plan. user: your own reports. team: your team's reports; empty if you are not in a team. alerted: reports from the last year with detections from your or your team's detection rules.
limit1 through 100; defaults to 25.
cursorOpaque continuation token from the prior page.
curl --fail-with-body --get \
--header "x-apikey: ${URLQUERY_API_KEY}" \
--data-urlencode 'scope=user' \
--data-urlencode 'limit=25' \
https://api.urlquery.net/public/v2/reports/recent
GET /public/v2/reports/related
ParameterValues
scopeip, asn, or domain. Required.
valueAn IPv4 or IPv6 address, an ASN from 0 through 4294967295, or a domain of at most 253 characters. Required.
limit1 through 100; defaults to 25.
cursorOpaque continuation token from the prior page.

Related reports match the report's target, meaning the IP address, ASN, or domain of the analyzed URL, not every server the page contacted. They include public reports only, plus restricted reports for accounts with restricted access when scope=ip.

curl --fail-with-body --get \
--header "x-apikey: ${URLQUERY_API_KEY}" \
--data-urlencode 'scope=domain' \
--data-urlencode 'value=example.com' \
https://api.urlquery.net/public/v2/reports/related

Search reports​

GET /public/v2/reports/search
ParameterValues
querySearch expression, up to 8192 characters. Required. See the search syntax guide.
limit1 through 100; defaults to 25.
offset0 through 10000; defaults to 0. offset plus limit must be at most 10000.

Search covers reports from the last year. Narrow it with a date range in the query, for example date:[2026-05-01 TO 2026-05-09].

curl --fail-with-body --get \
--header "x-apikey: ${URLQUERY_API_KEY}" \
--data-urlencode 'query=tags:phishing AND date:[2026-05-01 TO 2026-05-09]' \
--data-urlencode 'limit=25' \
https://api.urlquery.net/public/v2/reports/search
{
"success": true,
"data": {
"query": "tags:phishing AND date:[2026-05-01 TO 2026-05-09]",
"items": [],
"page": {"limit": 25, "offset": 0, "total_hits": 42}
}
}

items uses the overview format. Results are filtered by visibility after matching, so a page can hold fewer than limit items, and total_hits counts matches before that filtering. To read the next page, add limit to offset; do not use the number of items returned.

Pagination​

Recent and related lists place items and page under data:

{
"success": true,
"data": {
"items": [],
"page": {
"limit": 25,
"next_cursor": "<OPAQUE_CURSOR>",
"has_more": true
}
}
}

Send next_cursor unchanged as cursor with the same scope and value until has_more is false. Do not parse or modify it. A page can hold fewer than limit items, or none, while has_more is true, because visibility is checked after a page is selected. An empty collection returns 200 OK with items: [].

V2 errors​

{
"success": false,
"error": {
"http_code": 404,
"error": "NOT_FOUND",
"message": "the requested resource was not found"
}
}
StatusErrorWhen
400BAD_REQUESTA parameter is missing or invalid, a cursor was reused with different parameters, or the search query is invalid.
401MISSING_API_KEYThe x-apikey header is missing.
403INVALID_API_KEYThe key is invalid or disabled, or could not be verified.
403FORBIDDENYour key is not allowed to read reports.
404NOT_FOUNDThe report or resource does not exist, or you cannot see it.
429RATE_LIMIT_EXCEEDEDA quota is exhausted. Wait for Retry-After seconds.
502BAD_GATEWAYThe report service failed or is unavailable. Retry later.
503RATE_LIMIT_UNAVAILABLEQuota enforcement is temporarily unavailable. Retry later.
504GATEWAY_TIMEOUTThe report service timed out. Retry later.
500INTERNAL_ERRORAn unexpected failure. Retry later.