Exercism Solution
Parse a single published Exercism solution page into structured JSON with its track, exercise, author, language, iteration history, and full source code.
API usage
Add &scraper=exercism-solution to a Crawling API request. URL-encode the target URL in the url parameter.
curl 'https://api.crawlbase.com/?token=YOUR_TOKEN' \
--data-urlencode 'url=https://exercism.org/tracks/ruby/exercises/two-fer/solutions/neilnorthrop' \
--data-urlencode 'scraper=exercism-solution' -Gfrom crawlbase import CrawlingAPI
api = CrawlingAPI({'token': 'YOUR_TOKEN'})
res = api.get(
'https://exercism.org/tracks/ruby/exercises/two-fer/solutions/neilnorthrop',
{'scraper': 'exercism-solution'}
)
import json
data = json.loads(res['body'])const { CrawlingAPI } = require('crawlbase');
const api = new CrawlingAPI({ token: 'YOUR_TOKEN' });
const res = await api.get(
'https://exercism.org/tracks/ruby/exercises/two-fer/solutions/neilnorthrop',
{ scraper: 'exercism-solution' }
);
const data = JSON.parse(res.body);require 'crawlbase'
api = Crawlbase::API.new(token: 'YOUR_TOKEN')
res = api.get('https://exercism.org/tracks/ruby/exercises/two-fer/solutions/neilnorthrop', scraper: 'exercism-solution')
data = JSON.parse(res.body)Example input URL
Any single published Exercism solution page works in the url parameter - the page at /tracks/<track>/exercises/<slug>/solutions/<handle>. For example:
https://exercism.org/tracks/ruby/exercises/two-fer/solutions/neilnorthrop
https://exercism.org/tracks/go/exercises/hello-world/solutions/erikschierboomResponse shape
JSON response body. Field types may be null when the source page omits the value.
URL of the solution page that was scraped.
Track the solution belongs to.
Track slug (for example
ruby).Track display title (for example
Ruby).URL of the track icon.
Exercise the solution belongs to.
Exercise slug (for example
two-fer).Exercise type (for example
practice or concept).Exercise display title.
URL of the exercise icon.
Difficulty label (for example
easy, medium, hard).Short exercise description.
Author of the solution.
Author handle (Exercism username).
Programming language of the solution.
Editor indent size the author used, or null when not reported.
Number of stars on the solution.
Number of iterations in the
iterations array.True when the solution is out of date with the current exercise.
Index (
idx) of the iteration that is published, or null when none.Publish time of the solution (ISO 8601), or null when absent.
Iteration history for the solution, oldest first.
Iteration index (1-based).
Analysis status of the iteration (for example
no_automated_feedback).Test run status of the iteration (for example
passed).How the iteration was submitted (for example
cli or api).Creation time of the iteration (ISO 8601), or null when absent.
True when this iteration is the published one.
True when this iteration is the most recent.
Full source code of the published solution, or null when absent.
Sample response
{
"url": "https://exercism.org/tracks/ruby/exercises/two-fer/solutions/neilnorthrop",
"track": {
"slug": "ruby",
"title": "Ruby",
"iconUrl": "https://assets.exercism.org/tracks/ruby.svg"
},
"exercise": {
"slug": "two-fer",
"type": "practice",
"title": "Two Fer",
"iconUrl": "https://assets.exercism.org/exercises/two-fer.svg",
"difficulty": "easy",
"blurb": "Create a sentence of the form \"One for X, one for me.\""
},
"author": {
"handle": "neilnorthrop"
},
"language": "ruby",
"indentSize": 2,
"numStars": 42,
"numIterations": 2,
"isOutOfDate": false,
"publishedIterationIdx": 2,
"publishedAt": "2026-05-18T14:03:27Z",
"iterations": [
{
"idx": 1,
"status": "no_automated_feedback",
"testsStatus": "passed",
"submissionMethod": "cli",
"createdAt": "2026-05-17T22:41:03Z",
"isPublished": false,
"isLatest": false
},
{
"idx": 2,
"status": "no_automated_feedback",
"testsStatus": "passed",
"submissionMethod": "cli",
"createdAt": "2026-05-18T14:03:27Z",
"isPublished": true,
"isLatest": true
}
],
"code": "def two_fer(name = \"you\")\n \"One for #{name}, one for me.\"\nend"
}