Programmatic access to bluepages.fyi
The Bluepages API allows you to query crypto address ↔ Twitter mappings programmatically. All endpoints use the x402 payment protocol for micropayments on Base mainnet.
/check
$0.001
Check if an address or Twitter handle exists in the database.
Query params: ?address=0x... or
?twitter=@handle
Response format:
{
"timestamp": "2025-11-05T12:00:00.000Z",
"query": {
"type": "twitter",
"value": "@vitalikbuterin"
},
"exists": true,
"twitter": true,
"farcaster": false,
"message": "✓ Found in database. Use /data endpoint ($0.05) to get full details."
}
Note: exists is true if either twitter OR
farcaster is true.
/data
$0.05
Get full data for an address or Twitter handle.
Query params: ?address=0x... or
?twitter=@handle
Response format (address with both Twitter & Farcaster):
{
"timestamp": "2025-11-05T12:00:00.000Z",
"query": {
"type": "address",
"value": "0x1db3439a222c519ab44bb1144fc28167b4fa6ee6"
},
"found": true,
"address": "0x1db3439a222c519ab44bb1144fc28167b4fa6ee6",
"twitter": "@vitalikbuterin",
"twitterMetadata": {
"displayName": "vitalik.eth",
"ens": "vitalik.eth",
"source": "manual"
},
"twitterPriority": 2,
"farcaster": "@vitalik",
"farcasterMetadata": {
"displayName": "Vitalik Buterin",
"source": "farcaster"
},
"farcasterPriority": 1
}
Note: If Twitter or Farcaster is not available, those fields will be omitted.
/batch/check
$0.04 (bulk)
Check up to 50 addresses/Twitter handles at once (20% discount).
Request body:
{
"addresses": ["0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6", ...],
"twitters": ["@vitalikbuterin", "@jessepollak", ...]
}
Response format:
{
"results": [
{
"query": "0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6",
"exists": true,
"type": "address"
},
{
"query": "@vitalikbuterin",
"exists": true,
"type": "twitter"
},
{
"query": "@nonexistent",
"exists": false,
"type": "twitter"
}
]
}
/batch/data
$2.00 (bulk)
Get full data for up to 50 addresses/Twitter handles at once (20% discount).
Request body:
{
"addresses": ["0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6", ...],
"twitters": ["@vitalikbuterin", "@jessepollak", ...]
}
Response format:
{
"results": [
{
"query": "0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6",
"found": true,
"type": "address",
"data": {
"address": "0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6",
"twitter": "@vitalikbuterin",
"ens": "vitalik.eth",
"source": "manual"
}
},
{
"query": "@jessepollak",
"found": true,
"type": "twitter",
"data": {
"address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"twitter": "@jessepollak",
"ens": "jessepollak.eth",
"source": "farcaster"
}
},
{
"query": "@nonexistent",
"found": false,
"type": "twitter",
"data": null
}
]
}
Note: When found: false, the data field will be
null.
/my-data
FREE
Look up your own data for free by signing a message from your wallet (rate limited to once per 15 minutes).
Request body:
{
"address": "0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6",
"signature": "0x..." // EIP-712 signature from the address
}
Response format:
{
"success": true,
"address": "0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6",
"found": true,
"twitter": "@vitalikbuterin",
"farcaster": "@vitalik",
"metadata": {
"source": "manual",
"ens": "vitalik.eth"
}
}
// If not found:
{
"success": true,
"found": false,
"message": "No data found for this address"
}
Note: The signature must be an EIP-712 signature of the message "View my data on bluepages.fyi" from the specified address.
// Install: npm install ethers x402-fetch
import { Wallet } from 'ethers';
import { fetchWithPayment } from 'x402-fetch';
const PRIVATE_KEY = 'your_private_key_here';
const API_URL = 'https://bluepages.fyi'; // or http://localhost:4021
const wallet = new Wallet(PRIVATE_KEY);
async function checkAddress(address) {
const url = `${API_URL}/check?address=${address}`;
const response = await fetchWithPayment(url, {
method: 'GET',
wallet: wallet,
network: 'base'
});
const data = await response.json();
console.log(data);
return data;
}
async function getTwitter(address) {
const url = `${API_URL}/data?address=${address}`;
const response = await fetchWithPayment(url, {
method: 'GET',
wallet: wallet,
network: 'base'
});
const data = await response.json();
console.log('Twitter:', data.twitter);
return data;
}
// Usage
checkAddress('0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6');
getTwitter('0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6');
async function batchCheck(queries) {
const url = `${API_URL}/batch/check`;
const response = await fetchWithPayment(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ queries }),
wallet: wallet,
network: 'base'
});
const data = await response.json();
console.log(data);
return data;
}
// Check up to 50 at once
batchCheck([
'0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6',
'@vitalikbuterin',
'0x...'
]);
# Install: pip install eth-account requests
import os
import requests
import time
from eth_account import Account
from eth_account.messages import encode_typed_data
PRIVATE_KEY = os.getenv('PRIVATE_KEY')
API_URL = 'https://bluepages.fyi' # or http://localhost:4021
account = Account.from_key(PRIVATE_KEY)
def create_payment_header(facilitator_data):
"""Create x402 payment authorization header"""
typed_data = {
"types": {
"EIP712Domain": [
{"name": "name", "type": "string"},
{"name": "version", "type": "string"},
{"name": "chainId", "type": "uint256"},
{"name": "verifyingContract", "type": "address"}
],
"TransferWithAuthorization": [
{"name": "from", "type": "address"},
{"name": "to", "type": "address"},
{"name": "value", "type": "uint256"},
{"name": "validAfter", "type": "uint256"},
{"name": "validBefore", "type": "uint256"},
{"name": "nonce", "type": "bytes32"}
]
},
"primaryType": "TransferWithAuthorization",
"domain": facilitator_data["domain"],
"message": facilitator_data["message"]
}
encoded_msg = encode_typed_data(full_message=typed_data)
signed = account.sign_message(encoded_msg)
# Create payment object
payment = {
"paymentData": facilitator_data,
"userAddress": account.address,
"signature": signed.signature.hex()
}
import json, base64
return base64.b64encode(json.dumps(payment).encode()).decode()
def query_api(endpoint, params=None):
"""Query the API with x402 payment handling"""
url = f"{API_URL}{endpoint}"
# First request - expect 402
response = requests.get(url, params=params)
if response.status_code == 402:
# Get payment info from WWW-Authenticate header
auth_header = response.headers.get('WWW-Authenticate', '')
# Parse facilitator URL and request ID
import re
facilitator_match = re.search(r'facilitator="([^"]+)"', auth_header)
request_id_match = re.search(r'requestId="([^"]+)"', auth_header)
if facilitator_match and request_id_match:
facilitator_url = facilitator_match.group(1)
request_id = request_id_match.group(1)
# Get payment data from facilitator
pay_response = requests.get(
f"{facilitator_url}/requests/{request_id}/generate-payment-data",
params={"userAddress": account.address}
)
if pay_response.status_code == 200:
payment_data = pay_response.json()
# Create payment header
payment_header = create_payment_header(payment_data)
# Retry request with payment
response = requests.get(
url,
params=params,
headers={"X-PAYMENT": payment_header}
)
return response.json()
# Usage
def check_address(address):
return query_api('/check', {'address': address})
def get_twitter(address):
return query_api('/data', {'address': address})
# Example
result = check_address('0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6')
print(result)
data = get_twitter('0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6')
print('Twitter:', data.get('twitter'))
def batch_check(queries):
"""Check multiple addresses/Twitter handles at once"""
url = f"{API_URL}/batch/check"
# First request - expect 402
response = requests.post(
url,
json={"queries": queries},
headers={"Content-Type": "application/json"}
)
if response.status_code == 402:
# Same payment flow as above...
auth_header = response.headers.get('WWW-Authenticate', '')
# ... (payment handling code) ...
# Retry with payment
response = requests.post(
url,
json={"queries": queries},
headers={
"Content-Type": "application/json",
"X-PAYMENT": payment_header
}
)
return response.json()
# Check up to 50 at once
results = batch_check([
'0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6',
'@vitalikbuterin',
'0x...'
])
print(results)
# .env file
PRIVATE_KEY=your_private_key_here
# Load in code
import os
PRIVATE_KEY = os.getenv('PRIVATE_KEY')
| Endpoint | Single Price | Batch Price (per item) | Savings |
|---|---|---|---|
/check |
$0.001 USDC | $0.0008 USDC | 20% |
/data |
$0.05 USDC | $0.04 USDC | 20% |
Full working examples are available: