curl --request GET \
--url https://api.webacy.com/holder-analysis/{address} \
--header 'x-api-key: <api-key>'import requests
url = "https://api.webacy.com/holder-analysis/{address}"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://api.webacy.com/holder-analysis/{address}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.webacy.com/holder-analysis/{address}",
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: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.webacy.com/holder-analysis/{address}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.webacy.com/holder-analysis/{address}")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.webacy.com/holder-analysis/{address}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"token_address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"metadata": {
"name": "USD Coin",
"symbol": "USDC"
}
}Get detailed early holder analysis for a token
Analyzes token holders, buying patterns, and detects suspicious activity such as sniper bots and coordinated buys. This endpoint provides comprehensive insights into token ownership distribution, early investor behavior, and potential risk factors.
Supported Chains:
- Solana (
sol): Data reflects initial 10-hours window after mint with sniper detection. Early holder analysis is available for tokens launched within the last 12 months (data provider retention). Older tokens returndata_availability: unsupported_token_age; previously analyzed tokens continue to return stored results. - EVM chains (
eth,bsc,pol,arb,opt,base): Top holders and sniper detection. On BSC, early holder analysis is available for tokens deployed within the last 3 months (data provider retention). Older tokens returndata_availability: unsupported_token_age; previously analyzed tokens continue to return stored results. - Stellar (
stellar): Address must be inCODE:ISSUERformat - Sui (
sui): First buyers analysis with bundler detection - Hedera (
hedera): Accepts native0.0.Xformat (HTS token ID) or EVM address format. Includes token admin keys analysis (admin, freeze, wipe, pause, supply, KYC, fee schedule keys), custom fee schedules, and pause status. Sniper/bundling analysis is excluded (Hedera has deterministic transaction ordering, no MEV).
curl --request GET \
--url https://api.webacy.com/holder-analysis/{address} \
--header 'x-api-key: <api-key>'import requests
url = "https://api.webacy.com/holder-analysis/{address}"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://api.webacy.com/holder-analysis/{address}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.webacy.com/holder-analysis/{address}",
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: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.webacy.com/holder-analysis/{address}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.webacy.com/holder-analysis/{address}")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.webacy.com/holder-analysis/{address}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"token_address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"metadata": {
"name": "USD Coin",
"symbol": "USDC"
}
}data_availability: "unsupported_token_age" and a human-readable data_availability_message. Tokens analyzed before the retention cutoff continue to return their stored results.Telling “no data” apart from “no answer”
A successful response withtotal_holders_count: 0 and empty analysis blocks means exactly that: we looked, and there was nothing to report.
When we could not produce an answer, the response says so explicitly rather than looking like a zero. Always check data_availability before treating an empty result as a real finding:
data_availability | Meaning | What to do |
|---|---|---|
| (absent) | The analysis succeeded. An empty result is a genuine zero. | Use the result as-is. |
unsupported_token_age | The token predates the data provider’s retention window (see above). | Don’t retry — the answer won’t change. Previously analyzed tokens keep returning their stored results. |
provider_unavailable | An upstream data provider was unavailable for this request (rate limit, timeout, or an open circuit breaker), so no fresh analysis could be computed. | Retry. This is transient. |
data_availability_message, a human-readable explanation safe to surface to end users.
{
"token_address": "0xd1d2Eb1B1e90B638588728b4130137D262C87cae",
"data_availability": "provider_unavailable",
"data_availability_message": "Early holder analysis could not be computed because an upstream data provider was unavailable. This is a temporary condition — please retry.",
"total_holders_count": 0
}
data_availability is returned alongside HTTP 200, not an error status, because a partial result may still be present — for example a cached analysis served with reduced token metadata. Treating any 200 as a complete answer without checking this field can silently turn a provider outage into a “this token has zero holders” conclusion.Authorizations
Path Parameters
Token contract address. For Solana: mint address. For EVM chains: ERC-20 token contract address. For Stellar: 'CODE:ISSUER' format. For Hedera: HTS token ID in '0.0.X' native format (e.g., '0.0.8144307') or EVM address format.
Query Parameters
Blockchain network to analyze. Supported chains: sol (Solana), eth (Ethereum), bsc (BSC), pol (Polygon), arb (Arbitrum), opt (Optimism), base (Base), stellar (Stellar), sui (Sui), hedera (Hedera), robinhood (Robinhood Chain), tron (TRON). TRON returns a partial result: total_holders_count plus top_10_holders_analysis, including giniCoefficient and nakamotoCoefficient (computed by the upstream provider, currently TRON-only); first-buyer and sniper analysis are not produced for TRON. Very large TRC-20 tokens can exceed the provider query budget and respond with data_availability: "provider_unavailable".
sol, eth, bsc, pol, arb, opt, base, stellar, sui, hedera, robinhood, tron Whether to use cached data if available (default: true)
Whether to schedule a background refresh of analysis (default: false)
Maximum number of holders to analyze (default: 10000)
x <= 50000Response
Successful operation
Address of the analyzed token
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
Transaction hash of token mint
"4JqaQUsu5mRADKcHYCL9X1VNDEfZfTmbsXCTSuSJpBXgxbZGQYTHBvzdrHj11NfcDDVEXbELpnEZYVWfpnJ1mgU7"
Timestamp when token was minted
"2023-03-21T13:00:22.000Z"
Address of token minter
"FRgKuRNLRxTzChEKYgFZc5UiEBvZrBYNcRdmbEbXeS17"
Present when all or part of fresh holder analysis is unavailable. unsupported_token_age: the token launched before the data provider retention window (Solana: last 12 months, BSC: last 3 months); tokens analyzed before the cutoff continue to return stored results without this field. provider_unavailable: an upstream provider failed, so the response may contain partial data or no analysis data and should be retried.
unsupported_token_age, provider_unavailable "unsupported_token_age"
Human-readable explanation of the data availability limitation. Only present alongside data_availability.
"Early holder analysis is only available for Solana tokens launched within the last 12 months due to data provider retention limits. Previously analyzed tokens continue to return stored results."
Show child attributes
Show child attributes
Show child attributes
Show child attributes
{
"totalSupply": 10000000,
"percentageHeldByTop10": 87.5,
"expiresAt": 1741284889983,
"topHolders": [
{
"accountAddress": "TokenAccountAddress123",
"ownerAddress": "ARD9GAKA6LAzufwqZ3BTKcnJmaeNyGHp3n7UU4eiJ3mS",
"alias": "Raydium AMM",
"amount": 1000000,
"percentage": 12.34,
"label_info": {
"label_type": "dex",
"label_name": "Raydium AMM",
"label_subtype": "amm"
}
},
{
"accountAddress": "TokenAccountAddress456",
"ownerAddress": "BRwMfwzJG3aQpr9JZPk5GbZkZSfVW4vBqqTDjykn3bgB",
"alias": "Jupiter Exchange",
"amount": 750000,
"percentage": 7.5,
"label_info": {
"label_type": "dex",
"label_name": "Jupiter Exchange",
"label_subtype": "swap"
}
}
]
}
Number of tokens launched by the same developer in 24 hours
3
Show child attributes
Show child attributes
Token metadata information including name, symbol, links, and other details
Show child attributes
Show child attributes
