Weibo Data API: Time-Based Search, Post Details and Comments
Search Weibo by keyword and time range, retrieve post details and paginate comments with MID and maxId. Includes a bounded Python workflow and JSON export.
Organize collection around a topic and time range
To research a product discussion or campaign on Weibo, first narrow the keyword and time range, then retrieve matching posts and their comments. Just One API provides an endpoint for each step, letting you retain the relationships between posts and discussions.
This tutorial searches for “露营” (camping), reads up to two search pages, selects three posts and retrieves details plus up to two comment pages per post. Replace the keyword and dates to test your own research question with a bounded number of requests.
Get a token and test a search
Register for Just One API, obtain your API token and try Weibo Keyword Search V2 in the interactive documentation. One token works across platforms, with usage-based billing. Check your account for endpoint permissions and free trial allowances.
All three endpoints use GET and the token query parameter. Check the response body's business code=0 before processing data. The Python example reads the token from an environment variable and does not print complete request URLs.
Step 1: Search by date and hour
The search path is /api/weibo/search-all/v2. Supply these parameters:
q: the keyword, such as “露营”.startDayandendDay: dates inYYYY-MM-DDformat.startHourandendHour: hours from 0 to 23; the example uses 0 and 23.page: the search page, starting at 1.
Both dates and hours are required by this endpoint. The example also sets hotSort=false and contains=ALL. Documented media filters include PICTURE, VIDEO, MUSIC and LINK.
In the current public response example, posts are in data.weibo_list. Use each post's id for the detail request and inspect data.has_next_page before continuing. Restart pagination when changing the keyword or time range. Search results provide a research sample, not a guaranteed complete list of every relevant post in that period.
Step 2: Retrieve details and the post's MID
Send the search result's id to Post Details V1 at /api/weibo/get-weibo-detail/v1.
The current public example places the post object at data.status, including id, mid, text and created_at. The next request uses the mid returned in this object. Search results may also contain identifiers such as bid; do not assume all identifier forms are interchangeable across endpoints.
The script saves details before reading the MID. If it is missing, execution stops with a prompt to inspect the saved response instead of guessing a comment parameter. Post text may contain links or formatting, so keep the original text when creating a cleaned version.
Step 3: Paginate comments using maxId
Call Post Comments V1 at /api/weibo/get-post-comments/v1, supplying mid and sort=TIME.
Comments use cursor pagination. Omit maxId for the first request. For the next request, pass the returned data.max_id as the maxId parameter. This is separate from the search endpoint's page numbers; do not increment a comment cursor as though it were a page count.
The current example has an inner data.ok status, which is 1 on success, and a comment array at data.data. The script checks the status, deduplicates by comment ID and stops on an empty list, an empty or zero cursor, a repeated cursor, or the two-page limit.
Replies embedded in a comment response may be partial. They do not establish that you have a complete discussion tree. Retain post IDs, comment IDs and the collection scope when summarizing topics so your analysis remains traceable.
Python example: Save posts and comments
Install the dependency and set the environment variables in a macOS or Linux terminal. Replace the token and choose the dates you want to study.
python3 -m pip install requests
export JUSTONEAPI_TOKEN='your_token'
export WEIBO_START_DAY='2026-10-01'
export WEIBO_END_DAY='2026-10-07'Save the code as weibo_sample.py and run python3 weibo_sample.py. It makes at most 11 API requests: two searches, then one detail request and up to two comment requests for each of three posts. It makes fewer calls when results end early.
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
KEYWORD = "露营"
START_DAY = os.environ.get("WEIBO_START_DAY", "")
END_DAY = os.environ.get("WEIBO_END_DAY", "")
MAX_SEARCH_PAGES = 2
MAX_POSTS = 3
MAX_COMMENT_PAGES = 2
def main():
try:
start = datetime.strptime(START_DAY, "%Y-%m-%d")
end = datetime.strptime(END_DAY, "%Y-%m-%d")
except ValueError:
raise RuntimeError("Set WEIBO_START_DAY and WEIBO_END_DAY: YYYY-MM-DD") from None
if start > end:
raise RuntimeError("Start date must not be after end date")
folder = output_folder("weibo")
ids, seen = [], set()
for page in range(1, MAX_SEARCH_PAGES + 1):
result = call_api(
"/api/weibo/search-all/v2", q=KEYWORD,
startDay=START_DAY, startHour=0, endDay=END_DAY, endHour=23,
hotSort="false", contains="ALL", page=page,
)
save_json(folder, f"search-{page}.json", result)
data = result["data"]
rows = require_list(data, "weibo_list")
if not rows:
break
previous_count = len(ids)
for row in rows:
post_id = row.get("id") if isinstance(row, dict) else None
if post_id and str(post_id) not in seen:
seen.add(str(post_id))
ids.append(str(post_id))
if len(ids) == previous_count:
break
if data.get("has_next_page") not in (True, 1, "1"):
break
selected = ids[:MAX_POSTS]
save_json(folder, "selected-posts.json", selected)
for index, post_id in enumerate(selected, start=1):
detail = call_api("/api/weibo/get-weibo-detail/v1", id=post_id)
save_json(folder, f"post-{index}-detail.json", detail)
status = detail["data"].get("status")
mid = status.get("mid") if isinstance(status, dict) else None
if not mid:
raise RuntimeError("Missing post MID; inspect the saved detail")
cursor, cursors, comments, comment_ids = "", set(), [], set()
for page in range(1, MAX_COMMENT_PAGES + 1):
params = {"mid": str(mid), "sort": "TIME"}
if cursor:
params["maxId"] = cursor
result = call_api("/api/weibo/get-post-comments/v1", **params)
save_json(folder, f"post-{index}-comments-{page}.json", result)
data = result["data"]
if data.get("ok") not in (1, "1"):
raise RuntimeError("Comment response was unsuccessful")
rows = require_list(data, "data")
if not rows:
break
for row in rows:
if not isinstance(row, dict):
raise RuntimeError("Unexpected comment item")
cid = row.get("idstr") or row.get("id")
if cid is None:
raise RuntimeError("Missing comment ID; inspect saved JSON")
if str(cid) not in comment_ids:
comment_ids.add(str(cid))
comments.append(row)
next_cursor = data.get("max_id")
if next_cursor in (None, "", 0, "0"):
break
cursor = str(next_cursor)
if cursor in cursors:
break
cursors.add(cursor)
save_json(folder, f"post-{index}-comments.json", comments)
print(f"Saved {len(selected)} post samples to {folder}")
if __name__ == "__main__":
try:
main()
except RuntimeError as error:
raise SystemExit(str(error)) from NoneInspect the results and add your analysis
Each run creates a dated folder under weibo-output. selected-posts.json records the chosen posts. post-*-detail.json saves details, post-*-comments-*.json retains individual comment pages, and post-*-comments.json contains deduplicated comments for that post.
Group comments by post, time or topic to investigate recurring questions and product feedback. Preserve original text alongside cleaned text, labels or sentiment estimates. Review automated classifications, particularly where sarcasm, quotation or missing context can change the meaning.
Common questions
Can I use this workflow to track a topic over time?
Yes, by adding scheduled queries and storage. Retain the keyword, time window and retrieval time for each run, and deduplicate post and comment IDs across batches. Available search and comment coverage depends on actual responses; repeated collection does not guarantee exhaustive monitoring.
What if the next page repeats or returns nothing?
Search uses has_next_page and newly seen IDs. Comments use the returned max_id cursor. Keep the raw response and stop the current pagination sequence rather than repeating the same request indefinitely. Increase the sample limits only after checking the initial results.
Will failed requests be retried automatically?
No. First distinguish parameter, permission, rate-limit and transient failures. Then add bounded retries following the API failure guide. Running the script again creates a new directory and does not overwrite earlier results.
Try a short time window in the Weibo search documentation, then connect the detail and comment steps.
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.