Ruangguru APIapp.ruangguru.com ↗
Access Indonesian university entrance exam questions, answer options, correct answers, and explanations across all SNBT subjects via 5 structured endpoints.
What is the Ruangguru API?
The Ruangguru app.ruangguru.com API exposes 5 endpoints covering the full UTBK/SNBT question bank, including subjects, question sets, and complete per-question data. The get_questions endpoint returns each question's text, HTML, answer options, correct answer, and explanation for a given tryout serial. Two additional endpoints — list_subjects and list_question_sets — let you navigate the subject catalog and filter question sets by difficulty, lock status, and attempt count before fetching question content.
No input parameters required.
curl -X GET 'https://api.parse.bot/scraper/335b17d7-0522-4432-b077-6f006a1d39fc/list_subjects' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace app-ruangguru-com-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: Ruangguru UTBK/SNBT Question Bank — browse subjects, drill into questions."""
from parse_apis.ruangguru_utbk_snbt_question_bank_api import (
Ruangguru, QuestionSetNotFound
)
client = Ruangguru()
# List all UTBK subjects available in the question bank.
for subject in client.subjects.list(limit=5):
print(subject.name, subject.slug)
# Construct a subject and list its question sets, take the first free one.
subj = client.subject(slug="kemampuan-penalaran-umum")
qs = subj.question_sets.list(limit=3).first()
if qs:
print(qs.name, qs.serial, "free:", qs.is_free, "questions:", qs.total_questions)
# Get the full exam with questions, answers, and explanations.
exam = qs.exam()
print("Exam session:", exam.session_serial, "time:", exam.time_span_seconds, "s")
for q in exam.questions[:2]:
print(f" Q{q.number}: {q.question_text[:60]}... answer={q.correct_answer}")
# Get tryout detail with topics and rewards.
try:
detail = qs.detail()
print("Detail:", detail.name, "level:", detail.level, "duration:", detail.duration_seconds)
for topic in detail.topics:
print(f" Topic: {topic.name}")
except QuestionSetNotFound as exc:
print(f"Question set not found: {exc}")
# Browse tryout event categories.
for cat in client.tryoutcategories.list(limit=3):
print(cat.name, cat.product_type)
print("exercised: subjects.list / question_sets.list / exam / detail / tryoutcategories.list")
List all available UTBK/SNBT subjects in the question bank. Returns subject names, slugs, and icon URLs for the UTBK & Ujian Mandiri grade. The full subject catalog is returned in a single page.
No input parameters required.
{
"type": "object",
"fields": {
"grade": "string - Grade slug identifier",
"subjects": "array of subject objects each containing name, slug, and icon URL",
"grade_name": "string - Human-readable grade name",
"total_subjects": "integer - Total number of subjects"
}
}About the Ruangguru API
Subject and Question Set Discovery
Start with list_subjects, which returns the full catalog of UTBK/SNBT subjects in a single response. Each subject object includes a name, slug, and icon_url, plus the enclosing grade_name ("UTBK & Ujian Mandiri") and a total_subjects count. Pass any slug value into list_question_sets to retrieve all tryout question sets for that subject. Each question set carries a serial (format: RTO-XXXXXXX), level (difficulty), total_questions, is_free, is_locked, and total_user_attempts — useful for sorting by popularity or filtering to unlocked content.
Retrieving Questions and Answers
Pass a valid serial to get_questions to retrieve every question in that tryout. Each question object includes number, type, question_text, question_html, a full options array, correct_answer, and an explanation field. The endpoint also returns session_serial, total_questions, and time_span_seconds for the session. Free question sets (is_free: true from list_question_sets) are guaranteed to return full content.
Tryout Metadata and Categories
get_tryout_detail accepts a serial and returns structured metadata: topics (with nested subtopics), duration_seconds, level, rewards, and curriculum_serial. This is useful for building study plans or categorizing questions by topic area without fetching question content. list_tryout_categories provides a paginated list of tryout event types (Regular, Flexi, Kedinasan), each with id, name, description, banner_url, and product_type. Use page and page_size parameters to paginate results.
The Ruangguru API is a managed, monitored endpoint for app.ruangguru.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when app.ruangguru.com changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official app.ruangguru.com API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Build an SNBT practice app that pulls questions, options, and explanations via
get_questionsfor each subject. - Classify exam questions by topic and subtopic using the
topicsarray fromget_tryout_detail. - Display a subject catalog with icons by consuming the
list_subjectsendpoint. - Filter question sets by difficulty level and free/locked status using
list_question_setsfields before loading content. - Generate study-planning dashboards showing question counts and durations per tryout using
duration_secondsandtotal_questions. - Aggregate attempt counts from
total_user_attemptsinlist_question_setsto surface the most-attempted tryouts. - Browse exam event types (Regular, Flexi, Kedinasan) for categorized tryout listings via
list_tryout_categories.
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does Ruangguru offer an official public developer API?+
What does `get_questions` return for each question, and does it include explanations?+
get_questions includes question_text, question_html, an options array with all answer choices, correct_answer, and an explanation field. It also returns session-level metadata: session_serial, total_questions, and time_span_seconds.Are all question sets accessible, or only free ones?+
list_question_sets returns an is_free and is_locked flag for every question set. Free question sets (is_free: true) are guaranteed to return full question content via get_questions. Locked question sets may not return full data. You can fork this API on Parse and revise it to add filtering or handling logic for locked content if your use case requires it.Does the API cover subjects outside of UTBK/SNBT, such as high school or elementary school content?+
Does `list_question_sets` support filtering by difficulty or free status directly as query parameters?+
subject slug to scope results to a specific subject. Filtering by level or is_free is not a direct input parameter — those fields are returned in the response for client-side filtering. You can fork this API on Parse and revise it to add server-side filtering parameters for those fields.