API Docs

Real-time avatar lookup API: one phone number, one request, one response

The core is a realtime single lookup: POST one identifier to /api/v1/check with service_type=ws_avatar (a phone number) or service_type=email_avatar (an email address). Whether the account has a public avatar — and the image URL when it does — comes back in that same response: no polling, no callbacks. The same API key can also submit up to 100 identifiers at once for a synchronous response.

API endpointPOST
/api/v1/check
X-API-Key headercode · msg · data
Last updated: September 18, 2026service_type=ws_avatar | email_avatarread data.avatar_url
API at a glanceThe primary endpoint is the realtime single check; the multi, async bulk and balance endpoints share the same API key contract and the same code / msg / data response shape.

Quickstart

  1. 1.Create an API key in Settings.
  2. 2.Call GET /api/v1/balance to check the current balance.
  3. 3.POST one identifier to /api/v1/check, or up to 100 identifiers to /api/v1/batch-check.
  4. 4.Read data.avatar and data.avatar_url in the synchronous response.

Authentication

Use an API key created in Settings and send it with every request.

X-API-Key: sk_your_api_key
Keep your API key secret
Always call this endpoint from your server. Anyone holding the key can spend your balance.

Product and result fields

ws_avatar

WhatsApp Avatar Profile

Check whether a phone number has a public WhatsApp avatar, get the image URL, and read the portrait attributes of that avatar.

01

Single check

curl -X POST "https://avatarlookup.com/api/v1/check" \
  -H "X-API-Key: sk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "service_type": "ws_avatar", "identifier": "+14155552671" }'
Account found
{
  "code": 0,
  "msg": "ok",
  "data": {
    "service_type": "ws_avatar",
    "identifier": "+14155552671",
    "registered": true,
    "avatar": true,
    "avatar_url": "https://pps.whatsapp.net/v/example.jpg",
    "extra": {
      "profile_available": "true",
      "category": "individual portrait",
      "gender": "male",
      "age": "39",
      "skin_color": "white",
      "hair_color": "brown"
    }
  }
}
No account
{
  "code": 0,
  "msg": "ok",
  "data": {
    "service_type": "ws_avatar",
    "identifier": "+14155550000",
    "registered": false,
    "avatar": false,
    "avatar_url": "",
    "extra": {
      "profile_available": false,
      "category": "",
      "gender": "",
      "age": "",
      "skin_color": "",
      "hair_color": ""
    }
  }
}
registeredbooleanWhether the phone number is registered on WhatsApp.
avatarbooleanWhether a public profile photo is set.
avatar_urlstringURL of the public profile photo; empty string when no photo is set.
extra.profile_availablebooleanWhether portrait attributes were produced this time. Read it together with avatar: false/false means there is no avatar to analyse, true/false means the avatar could not be recognized.
extra.categorystringWhat the picture is: individual portrait, group photo, game avatar, cartoon avatar, landscape, pet avatar or object.
extra.genderstringmale, female or unknown.
extra.agenumberEstimated age, accurate to about 3 years and clamped to 0-80. Empty when no gender was determined — there is no placeholder number.
extra.skin_colorstringDescriptive skin tone, for example white, east_asian or hispanic. Treat it as an open set.
extra.hair_colorstringDescriptive hair colour, for example black, brown, blond or gray white. Treat it as an open set.
02

Multi check

Pricing: per phone number

Each phone number in the payload is billed independently. Maximum 100 phone numbers per request. Only successfully checked phone numbers consume balance. If your balance cannot cover the full batch, the request is rejected before processing.

Submit up to 100 phone numbers in one request; results are returned in the same order.

curl -X POST "https://avatarlookup.com/api/v1/batch-check" \
  -H "X-API-Key: sk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "service_type": "ws_avatar", "identifiers": ["+14155552671", "+14155550000"] }'
{
  "code": 0,
  "msg": "ok",
  "data": {
    "service_type": "ws_avatar",
    "total": 2,
    "succeeded": 1,
    "failed": 1,
    "results": [
      {
        "identifier": "+14155552671",
        "exists": true,
        "registered": true,
        "avatar": true,
        "avatar_url": "https://pps.whatsapp.net/v/example.jpg",
        "extra": {
          "profile_available": "true",
          "category": "individual portrait",
          "gender": "male",
          "age": "39",
          "skin_color": "white",
          "hair_color": "brown"
        }
      },
      {
        "identifier": "+14155550000",
        "exists": false
      }
    ]
  }
}
existsbooleanWhether this phone number produced a result. false means the format was invalid, the result was undetermined, or the check failed; when false, none of the fields below are present.
registeredbooleanWhether the account exists on that platform. Present only when exists is true, with the same meaning as the single lookup.
avatarbooleanWhether a public profile photo is set.
avatar_urlstringURL of the public profile photo; empty string when no photo is set.
extra.profile_availablebooleanWhether portrait attributes were produced this time. Read it together with avatar: false/false means there is no avatar to analyse, true/false means the avatar could not be recognized.
extra.categorystringWhat the picture is: individual portrait, group photo, game avatar, cartoon avatar, landscape, pet avatar or object.
extra.genderstringmale, female or unknown.
extra.agenumberEstimated age, accurate to about 3 years and clamped to 0-80. Empty when no gender was determined — there is no placeholder number.
extra.skin_colorstringDescriptive skin tone, for example white, east_asian or hispanic. Treat it as an open set.
extra.hair_colorstringDescriptive hair colour, for example black, brown, blond or gray white. Treat it as an open set.

Concurrency, timeouts, and retry behavior

Avatar lookups are synchronous. Use the returned code to decide whether to accept the result or retry later.

  • 5 requests in flight per userSingle and multi checks share this limit, and a multi request counts as one request no matter how many phone numbers it carries. On top of that, only one multi check per account runs at a time; a second one is rejected until the first finishes. Hitting either limit returns code 42901 immediately with no charge, plus a Retry-After header — resubmit once an in-flight request finishes.
  • 60s single, 300s multiExceeding the time limit returns code 50400 with no charge. A multi check that times out fails as a whole — no partial results, and the full amount is refunded.
  • A multi check takes up to 100 phone numbersResults preserve submission order and length. One multi check per account runs at a time; submit the next batch once the previous one has returned.

Error codes

40000Unsupported service type or conflicting request fields
40001Invalid JSON body
40002Invalid phone number
40100Missing or invalid API key
40200Insufficient balance
42200The phone number could not be determined at this time. No data is returned and the request is not charged
42900A usage quota is exhausted, or there are too many unfinished orders
42901All five in-flight request slots are occupied, or a multi check is already running on this account; submit after an in-flight request finishes. The rejected request is not charged and carries a Retry-After header
50303The service is at capacity right now; not charged. Wait for the Retry-After seconds and resubmit the same request
50400The check did not finish within its timeout and is not charged; retry it. A batch timeout fails the whole batch and refunds the full amount
50300Validation service maintenance

Asynchronous bulk tasks

Upload a file of phone numbers and get a task id straight away. Then check the task by that id; once it succeeds you get a download link for the result archive.

  • ws_profile_batchWhatsApp avatar · Bulk1,000–100,000 phone numbers per task$0.005 per phone number
  • tg_profile_batchTelegram profile · Bulk1,000–100,000 phone numbers per task$0.004 per phone number
  • tg_username_profile_batchTelegram username profile · Bulk1,000–100,000 usernames per task$0.004 per username
  • viber_profile_batchViber profile · Bulk1,000–100,000 phone numbers per task$0.008 per phone number
  • max_profile_batchMAX profile · Bulk1,000–100,000 phone numbers per task$0.008 per phone number
  • line_profile_batchLINE profile · Bulk1,000–100,000 phone numbers per task$0.008 per phone number
  • zalo_profile_batchZalo profile · Bulk1,000–100,000 phone numbers per task$0.008 per phone number
  • email_avatar_batchEmail avatar · Bulk1,000–100,000 email addresses per task$0.003 per email address

1. Submit a file

curl -X POST "https://avatarlookup.com/api/v1/bulk-tasks" \
  -H "X-API-Key: sk_your_api_key" \
  -F service_type=ws_profile_batch \
  -F country=US \
  -F file=@numbers.txt
Response: task created (status processing)
{
  "code": 0,
  "msg": "ok",
  "data": {
    "id": "3f9c2a7d8e4b4c1a9f0e6b2d5c8a7e13",
    "product": "ws_profile_batch",
    "status": "processing",
    "country": "US",
    "total": 1000,
    "created_at": "2026-09-08T09:30:00Z"
  }
}

2. Check the task

curl "https://avatarlookup.com/api/v1/bulk-tasks/3f9c2a7d8e4b4c1a9f0e6b2d5c8a7e13" \
  -H "X-API-Key: sk_your_api_key"
Response: task finished (result_url present once it succeeds)
{
  "code": 0,
  "msg": "ok",
  "data": {
    "id": "3f9c2a7d8e4b4c1a9f0e6b2d5c8a7e13",
    "product": "ws_profile_batch",
    "status": "success",
    "country": "US",
    "total": 1000,
    "success_cnt": 990,
    "failure_cnt": 10,
    "result_url": "https://…/result.zip",
    "created_at": "2026-09-08T09:30:00Z"
  }
}
  • One phone number per line.Upload a .txt or .csv with one phone number in E.164 form per line. Send `country` with the file: it completes numbers that have no country code, and the file is validated against it.
  • No per-phone number progress.status is processing, success or failed. Large lists take a while; do not poll more often than once every 30 seconds.
  • Billing.The full file is reserved on submit. When the task finishes you are charged only for the phone numbers that were actually checked and the rest is refunded. A failed task is refunded in full.
  • Result files expire.The download link is generated on demand and points at a time-limited file. Download the result soon after the task finishes.

Ready to start integrating?

Ready to get started? Create a free account and get your API key in seconds.