Back to blog
TutorialOctober 11, 20265 min read

Xiaohongshu Pugongying API: Creator Search, Rates and Audience Profiles

Build a Xiaohongshu Pugongying creator shortlist with Just One API. Filter by follower count, retrieve profiles and collaboration rates, and save audience data with Python.

Build a creator shortlist for a Xiaohongshu campaign

A useful creator shortlist combines discovery, collaboration rates and audience fit. Just One API provides Xiaohongshu Pugongying endpoints for each step: search for creators, retrieve their profiles, then inspect their follower distributions.

This tutorial searches for creators with 10,000–100,000 followers, reads at most two result pages, and retrieves profiles and audience data for up to three creators. Adjust the follower range to your project. The output is a shortlist for review; content quality and commercial suitability still need to be assessed.

For note content or comments, start with the Xiaohongshu versus Pugongying guide. This workflow uses the creator marketplace's marketing data.

Get a token and test a request

Register for Just One API, obtain your API token, and use the interactive documentation to test for free. One token works across platform APIs, with usage-based billing. Check your account for the permissions and trial allowance available for each endpoint.

Open Creator Search V1, enter your token and follower limits, and request page 1. Check the response body's business code: it must be 0 before you process the data. HTTP success alone is insufficient.

All three endpoints in this tutorial use GET and require a token query parameter. The script reads the token from an environment variable and avoids printing full request URLs containing it.

Step 1: Search and retain each creator's userId

The search endpoint is /api/xiaohongshu-pgy/api/solar/cooperator/blogger/v2/v1. The example sends:

  • fansNumberLower=10000 and fansNumberUpper=100000 for the follower range.
  • sort=FANS for descending follower count. Use DEFAULT for the platform's intelligent ranking.
  • page=1 for the first page, incrementing the page number for subsequent requests.

In the current public response example, creators appear in data.kols. Retain each row's userId for profile and audience requests. The script deduplicates these IDs before choosing a small sample.

The returned total describes the reported search result size; it is not a count of all creators on the platform. This example stops after two pages, an empty page, or a page with no new IDs. Restart at page 1 when changing filters.

Step 2: Read profiles and collaboration rates

Pass a selected userId to Creator Profile V1. The current public example includes data.name, data.fansCount, data.picturePrice, data.videoPrice and data.showPrice.

Image-post and video rates can be null. A null rate means no value was returned in that response; it does not mean a free collaboration. Preserve showPrice alongside the raw rates. Before comparing budgets, confirm the unit, content format and conditions associated with each quote.

The script saves complete profile responses and creates a compact shortlist.json. Search and profile data may reflect different retrieval times, so retain both source responses when values differ instead of silently overwriting one with the other.

Step 3: Retrieve follower distributions

Call Follower Distribution V1 with the same userId. The current example contains:

  • data.ages, with group and percent values.
  • data.gender for gender distribution.
  • data.provinces and data.cities for geography.
  • data.interests and data.devices for interest and device distributions.
  • data.dateKey for the audience data's date marker.

These fields help you assess audience fit. Check each metric's scale and denominator before charting it; do not automatically multiply every proportion by 100 or replace missing groups with zero. The script preserves the complete audience response and adds dateKey to the shortlist so its data period remains visible.

Python example: Export profiles and audience data

Install the dependency and set your token. Replace your_token with your own value. These commands work in a macOS or Linux terminal.

bash
python3 -m pip install requests
export JUSTONEAPI_TOKEN='your_token'

Save the code as pugongying_sample.py and run python3 pugongying_sample.py. It makes at most two search requests plus profile and audience requests for three creators: up to 8 API requests. It makes fewer calls if results end early or an error stops execution. These are sample limits, not service quotas.

python
import json
import os
from datetime import datetime, timezone
from pathlib import Path

import requests

BASE_URL = "https://api.justoneapi.com"
TOKEN = os.environ.get("JUSTONEAPI_TOKEN", "")


def call_api(path, **params):
    try:
        response = requests.get(
            BASE_URL + path,
            params={"token": TOKEN, **params},
            timeout=120, allow_redirects=False,
        )
    except requests.RequestException:
        raise RuntimeError("API network error or timeout") from None
    if response.status_code != 200:
        raise RuntimeError(f"API HTTP {response.status_code}")
    try:
        result = response.json()
    except ValueError:
        raise RuntimeError("API response is not JSON") from None
    if not isinstance(result, dict) or result.get("code") != 0:
        code = result.get("code") if isinstance(result, dict) else None
        raise RuntimeError(f"API failed: code={code}; check the docs")
    data = result.get("data")
    if not isinstance(data, dict):
        raise RuntimeError("Unexpected data shape; inspect the docs")
    inner = data.get("base_resp")
    if isinstance(inner, dict) and inner.get("status_code") not in (0, "0"):
        raise RuntimeError("Platform response was unsuccessful")
    return result


def save_json(folder, name, value):
    (folder / name).write_text(
        json.dumps(value, ensure_ascii=False, indent=2), encoding="utf-8"
    )


def require_list(data, key):
    value = data.get(key)
    if not isinstance(value, list):
        raise RuntimeError(f"Expected a list at {key}; inspect saved JSON")
    return value


def output_folder(topic):
    if not TOKEN or TOKEN == "your_token":
        raise RuntimeError("Set JUSTONEAPI_TOKEN before running")
    run_id = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%S%fZ")
    folder = Path(topic + "-output") / run_id
    folder.mkdir(parents=True, exist_ok=False)
    return folder


MAX_PAGES = 2
MAX_CREATORS = 3
SEARCH = "/api/xiaohongshu-pgy/api/solar/cooperator/blogger/v2/v1"
PROFILE = "/api/xiaohongshu-pgy/api/solar/cooperator/user/blogger/userId/v1"
AUDIENCE = "/api/xiaohongshu-pgy/api/solar/kol/data/userId/fans_profile/v1"


def main():
    folder = output_folder("pugongying")
    ids, seen = [], set()
    for page in range(1, MAX_PAGES + 1):
        result = call_api(
            SEARCH, page=page, sort="FANS",
            fansNumberLower=10000, fansNumberUpper=100000,
        )
        save_json(folder, f"search-{page}.json", result)
        rows = require_list(result["data"], "kols")
        if not rows:
            break
        previous_count = len(ids)
        for row in rows:
            uid = row.get("userId") if isinstance(row, dict) else None
            if uid and str(uid) not in seen:
                seen.add(str(uid))
                ids.append(str(uid))
        if len(ids) == previous_count:
            break

    selected = ids[:MAX_CREATORS]
    save_json(folder, "selected-creators.json", selected)
    summary = []
    for index, uid in enumerate(selected, start=1):
        profile = call_api(PROFILE, userId=uid)
        save_json(folder, f"creator-{index}-profile.json", profile)
        audience = call_api(AUDIENCE, userId=uid)
        save_json(folder, f"creator-{index}-audience.json", audience)
        data = profile["data"]
        summary.append({
            "userId": uid, "name": data.get("name"),
            "fansCount": data.get("fansCount"),
            "picturePrice": data.get("picturePrice"),
            "videoPrice": data.get("videoPrice"),
            "showPrice": data.get("showPrice"),
            "audienceDate": audience["data"].get("dateKey"),
        })
    save_json(folder, "shortlist.json", summary)
    print(f"Saved {len(selected)} creator samples to {folder}")


if __name__ == "__main__":
    try:
        main()
    except RuntimeError as error:
        raise SystemExit(str(error)) from None

Work with the saved shortlist

Each run creates a dated folder under pugongying-output. selected-creators.json contains the selected IDs. shortlist.json summarizes names, follower counts, raw rates and audience dates. The individual creator-*-profile.json and creator-*-audience.json files retain full responses.

Review the shortlist before expanding enrichment to more creators. This keeps the relationship between candidate volume and request count clear. If you export CSV, leave unknown rates empty and track missing data separately so spreadsheet totals do not treat unknown rates as zero cost.

Common questions

Can I skip search if I already have an ID?

Yes. Use the corresponding Pugongying userId to request the profile and follower distribution directly. Names can change or be shared by multiple creators; IDs are better join keys.

What should I do with missing rates or audience fields?

Distinguish a failed API request from a successful response with a null field or an empty list. The script stops on a business error and retains the successful responses already saved. It does not convert a failure into a valid creator record.

How can I keep the data updated?

Add scheduling and incremental storage around this workflow. Store snapshots by userId and retrieval time, retain the search filters, and set explicit page, concurrency and retry limits. See the API failure and retry guide before adding retries.

Start with one page in the creator search documentation, then generate a shortlist using your own criteria.

Continue with Just One API

Log in to the Dashboard for your token, read the full API docs, or open the MCP GitHub project for the latest configuration.