Introduction to exercises-dataset: How to install and use the 1324 fitness action data set

Introduce the data content, installation method, offline browsing, JSON reading, database import and API access process of hasaneyldrm/exercises-dataset, and remind you of the differences between media resources and fields.

hasaneyldrm/exercises-dataset is a dataset project for fitness application developers. It organizes fitness actions into structured JSON and comes with two front-end pages:index.htmlUsed to browse actions,setup.htmlUsed to assist in generating database import SQL, API call examples and back-end development tips.

According to the project README, the current data set covers 1,324 movements, including movement names, body parts, equipment, target muscles, auxiliary muscle groups, and step-by-step instructions. The project is suitable for fitness app prototypes, training planning tools, action search pages, recommendation system experiments, or as basic data when generating fitness API backends for large models.

You need to pay attention to one detail first: warehouse introduction, README,setup.htmland currentdata/exercises.jsonThe descriptions are not entirely consistent. The README clearly states that media images and GIFs are not distributed with the repository;setup.htmlThere is still the old description of “images/videos included”; it may also appear in the current raw JSONimage,gif_urlThis type of relative path field. When actually accessing, the current files in the warehouse should prevail. Do not default that pictures and animation files must be available.

What scene is suitable for

This project is not a complete fitness application, but a data base that can be directly connected to the application. You can understand it into three parts:

  • data/exercises.json: Core data file, which is what the application ultimately reads.
  • index.html: Local browser version action retrieval tool, no backend required.
  • setup.html: Developer integration wizard, providing database table creation, INSERT SQL generation, API examples and LLM prompt words.

If you just want to quickly view the data, openindex.htmlThat’s enough. If you want to put data into your product, you should start withdata/exercises.jsonTo get started, decide whether to read the JSON directly, import it into a database, or generate a layered REST API.

Installation and download

The easiest way is to clone the repository directly:

1
2
git clone https://github.com/hasaneyldrm/exercises-dataset.git
cd exercises-dataset

The warehouse itself is mainly static files and does not requirenpm install, and there are no backend services that must be started. After the cloning is completed, the directory will be as follows:

1
2
3
4
5
6
exercises-dataset/
├── data/
│   └── exercises.json
├── index.html
├── setup.html
└── README.md

If you just want to download the data file, you can also save the raw JSON directly:

1
curl -L -o exercises.json https://raw.githubusercontent.com/hasaneyldrm/exercises-dataset/main/data/exercises.json

Windows PowerShell can be downloaded like this:

1
2
3
Invoke-WebRequest `
  -Uri "https://raw.githubusercontent.com/hasaneyldrm/exercises-dataset/main/data/exercises.json" `
  -OutFile "exercises.json"

After downloading, it is recommended to confirm whether the file can be parsed normally:

1
python -m json.tool data/exercises.json > /tmp/exercises.pretty.json

Available under Windows:

1
python -m json.tool .\data\exercises.json > .\exercises.pretty.json

If an error is reported in this step, it means that the file download is incomplete. First, re-pull the warehouse or re-download the JSON.

Open browser tool locally

warehouseindex.htmlIt is a pure front-end browser that can be opened directly:

1
2
3
4
5
# macOS
open index.html

# Windows PowerShell
Start-Process .\index.html

It’s great for quickly checking movement data: search for movement names, filter by body part, machine, or target muscle, and click on a card to view instructions. Because the README has stated that media resources are not distributed with the warehouse, if the image or GIF is empty when browsing, it does not mean that the data loading failed.

If the browser restricts local file reading due to security policies, you can start a temporary static server in the warehouse directory:

1
python -m http.server 8000

Then visit:

1
http://localhost:8000/index.html

Node.js users can also use:

1
npx serve .

Then press the command line prompt to open the local address.

Use setup.html to generate database and API examples

setup.htmlIt is an integration wizard for developers. Open with andindex.htmlSame:

1
python -m http.server 8000

Then visit:

1
http://localhost:8000/setup.html

Its process mainly consists of three steps.

The first step is Database Setup. The page can switch database types such as SQL Server, PostgreSQL, MySQL, SQLite, etc., and copy the correspondingCREATE TABLEstatement and generates an INSERT SQL file containing 1,324 action data. This generation process is completed locally in the browser and does not require uploading data.

The second step is API Integration. You can enter your own API base URL, and the page will generate call examples in different languages, including cURL, JavaScript, Python, C#, Java, PHP, and Go. Example interfaces include:

1
2
3
GET /exercises/:id
GET /exercises?page=1&limit=20
GET /exercises?category=Strength&body_part=Chest

The interface here is not the online service already provided by the warehouse, but the interface shape that you are recommended to implement in your own backend. That is to say,setup.htmlHelp you organize the calling methods and will not start the API for you.

The third step is Ask Your LLM. Pages can generate prompts based on framework and database combinations, such as Express.js + PostgreSQL, FastAPI + SQLite, Spring Boot + MySQL, ASP.NET Core + SQL Server, Laravel, or Gin. You can paste the prompt words into ChatGPT, Claude or Gemini and let the model generate backend code based on the data structure.

Read JSON directly

If your application is not large in scale, read it directlydata/exercises.jsonis the fastest way. Python example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import json

with open("data/exercises.json", "r", encoding="utf-8") as f:
    exercises = json.load(f)

print("动作总数:", len(exercises))

chest = [item for item in exercises if item.get("category") == "chest"]
bodyweight = [item for item in exercises if item.get("equipment") == "body weight"]

print("胸部动作:", len(chest))
print("自重动作:", len(bodyweight))

first = exercises[0]
print(first["id"], first["name"])
print(first.get("instructions", {}).get("en"))

Node.js example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
const exercises = require("./data/exercises.json");

console.log("Total:", exercises.length);

const bodyweight = exercises.filter((item) => item.equipment === "body weight");
const byCategory = exercises.reduce((acc, item) => {
  const key = item.category || "unknown";
  acc[key] = acc[key] || [];
  acc[key].push(item);
  return acc;
}, {});

console.log("Bodyweight:", bodyweight.length);
console.log(Object.keys(byCategory));

In front-end projects, you can put JSON intopublic/data/exercises.json, then usefetchload:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
async function loadExercises() {
  const res = await fetch("/data/exercises.json");
  if (!res.ok) {
    throw new Error(`Failed to load exercises: ${res.status}`);
  }
  return await res.json();
}

loadExercises().then((exercises) => {
  console.log(exercises.length);
});

If using TypeScript, it is recommended to define a conservative type first. Due to differences between README and current JSON fields,image,gif_url,media_id,instruction_stepsSuch fields are best written as optional:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
type Exercise = {
  id: string;
  name: string;
  category?: string;
  body_part?: string;
  equipment?: string;
  target?: string;
  muscle_group?: string;
  secondary_muscles?: string[];
  instructions?: Record<string, string>;
  instruction_steps?: Record<string, string[]>;
  media_id?: string | null;
  image?: string | null;
  gif_url?: string | null;
  created_at?: string;
};

In this way, even if the warehouse subsequently adjusts fields, the application will not easily crash due to a missing field.

How to import database

For formal projects, it is recommended to import data into the database. The reason is simple: paging, filtering, searching, background editing, and API permission control are all easier to do.

A common table structure can be designed like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
CREATE TABLE exercises (
  id VARCHAR(32) PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  category VARCHAR(100),
  body_part VARCHAR(100),
  equipment VARCHAR(100),
  target VARCHAR(100),
  muscle_group VARCHAR(100),
  secondary_muscles JSON,
  instructions JSON,
  instruction_steps JSON,
  image VARCHAR(255),
  gif_url VARCHAR(255),
  media_id VARCHAR(100),
  created_at VARCHAR(64)
);

PostgreSQL can change JSON fields tojsonb:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
CREATE TABLE exercises (
  id text PRIMARY KEY,
  name text NOT NULL,
  category text,
  body_part text,
  equipment text,
  target text,
  muscle_group text,
  secondary_muscles jsonb,
  instructions jsonb,
  instruction_steps jsonb,
  image text,
  gif_url text,
  media_id text,
  created_at text
);

It is recommended that the import process be done in this order:

  1. usesetup.htmlGenerate table creation SQL and INSERT SQL for the corresponding database.
  2. Execute in the local database or test library first, do not directly import into the production library.
  3. Checks if the total number of rows is equal to the JSON array length.
  4. Build index: at least givecategory,body_part,equipment,targetAdd a normal index.
  5. If you want to do a keyword search, then consider full-text indexing or external search services.

For example, PostgreSQL can add these indexes first:

1
2
3
4
CREATE INDEX idx_exercises_category ON exercises(category);
CREATE INDEX idx_exercises_body_part ON exercises(body_part);
CREATE INDEX idx_exercises_equipment ON exercises(equipment);
CREATE INDEX idx_exercises_target ON exercises(target);

The backend API can first implement four types of interfaces:

1
2
3
4
GET /exercises
GET /exercises/:id
GET /exercises?category=chest
GET /exercises?equipment=body%20weight

It is recommended that the paging parameters be unified as:

1
page=1&limit=20

The response structure can remain stable:

1
2
3
4
5
6
{
  "items": [],
  "page": 1,
  "limit": 20,
  "total": 1324
}

This makes front-end lists, filters, and infinite scrolling easier to access.

How to deal with media resources

The README tip is important: Do not default to a repository that contains action images and GIFs that are directly commercially available. It states that the underlying data comes from ExerciseDB v1, media assets are not redistributed with the repository, and some records retain media references or relative paths.

There are three processing methods in actual projects:

  • Only use text data, do not display images and GIFs.
  • Prepare your own legally authorized action pictures or videos before using themidOr action name to establish mapping.
  • If you have the right to use ExerciseDB’s media resources, then access the corresponding CDN or resource address according to the relevant terms.

don’t putimage,gif_urlThe field is directly treated as “a file that must exist in the warehouse”. Before accessing, you should check:

1
2
ls images
ls videos

If the directory does not exist, the application must empty the media area or hide the image and animation entries.

Pitfalls that are easy to step on when accessing

First, fields may change. The fields in the README example and raw JSON are not consistent everywhere, so don’t make all fields required in your code. Especially media-related fields and multilingual fields should use optional reads.

Second, the categorical values ​​are in English lowercase style, for examplechest,back,upper legs,body weight. If your front-end displays Chinese, you should do a layer of mapping in the application:

1
2
3
4
5
6
7
8
const categoryLabel = {
  chest: "胸部",
  back: "背部",
  waist: "腰腹",
  "upper legs": "大腿",
  "upper arms": "上臂",
  shoulders: "肩部",
};

Third, action instructions are not medical advice. It is suitable for use as product prototypes, teaching content and action retrieval data, but formal fitness products should still include safety tips, contraindications and professional review processes.

Fourth, don’t ignore source and authorization. The README explains the source of the underlying data, reasons for non-distribution of media, and rights statement. ExerciseDB, Kaggle re-host, and the terms of use of the warehouse should be reconfirmed before commercial use.

If you are just doing a demonstration, you can directlygit clone,Openindex.html, and then fromdata/exercises.jsonRead data.

If you want to make a complete fitness application, you can proceed in this order:

  1. Clone the repository and pin a commit to prevent subsequent field changes from affecting the project.
  2. examinedata/exercises.jsonActual field and language coverage.
  3. usesetup.htmlGenerate database SQL and import the test library.
  4. accomplish/exercises,/exercises/:id, filtering and paging APIs.
  5. The front end displays text data, and the media area is first shorted.
  6. Supplement your own images, GIFs or videos, subject to licensing.

The advantage of this process is that it is simple, controllable, and will not be stuck by media authorization issues.exercises-datasetThe most valuable part is that it organizes fitness action knowledge into a data structure that can be directly read and retrieved; as for media display, training plan logic and personalized recommendations, they should be placed in your own application layer for further improvement.

记录并分享
Built with Hugo
Theme Stack designed by Jimmy