DEV Community

Airball Nick
Airball Nick

Posted on AI-assisted

I Opened the Palworld Breeding Dataset Behind My Calculator

I built a Palworld breeding calculator, but the part I most want other developers to use is the data.

The dataset behind the site is now public as JSON and CSV:

https://www.palworldonline.net/data

Disclosure: I built and maintain the calculator I am linking to here. It is free to use, does not require an account, and is not affiliated with Pocketpair or Garena.

This post is about what is in the dataset, why I opened it, and the breeding-data bugs it is designed to prevent.

What is available

There are four lightweight endpoints:

The data page also links the full Paldeck profile JSON used by newer lookup features.

The breeding exports cover Palworld 1.0 breeding data:

  • 299 Pal entries
  • 297 Pals that can enter a Breeding Farm
  • 183 ordinary formula-pool entries
  • 164 special combo rows
  • CombiRank values
  • parent-pair counts
  • element types
  • gender ratio
  • breedable and farm-eligible flags
  • gender fields for special combos

The endpoints are served with:

Access-Control-Allow-Origin: *
Enter fullscreen mode Exit fullscreen mode

That means you can fetch them from another browser-based tool without needing a proxy.

Quick example

type PalRow = {
  name: string;
  slug: string;
  combi_rank: number;
  rank_position: number;
  special_only: boolean;
  breedable: boolean;
  breeding_farm_eligible: boolean;
  parent_pair_count: number;
  elements: string[];
  male_percent: number;
  icon_url: string | null;
  guide_url: string;
};

type PalsResponse = {
  pals: PalRow[];
};

const data: PalsResponse = await fetch(
  "https://www.palworldonline.net/api/pals.json",
).then((response) => response.json());

const pals = data.pals;

const targets = pals
  .filter((pal) => pal.breedable && pal.parent_pair_count > 0)
  .sort((a, b) => b.parent_pair_count - a.parent_pair_count)
  .slice(0, 10);

console.table(targets.map((pal) => ({
  name: pal.name,
  pairs: pal.parent_pair_count,
  rank: pal.combi_rank,
})));
Enter fullscreen mode Exit fullscreen mode

For spreadsheet work, use the CSV versions. The schema is intentionally flat.

Why not just scrape a calculator?

Because breeding tools tend to hide the assumptions that matter.

If a site only shows the final child, you cannot tell:

  • whether special combos were applied before the formula
  • whether special-only children were excluded from the ordinary pool
  • whether the calculator knows about gender-dependent combo rows
  • whether farm-ineligible Pals were excluded
  • whether X + X -> X was interpreted too broadly

The public dataset exists so those assumptions are visible.

Correction 1: Katress + Wixen is gender-dependent

This was the row that broke my first implementation.

Katress + Wixen can produce two children:

  • female Katress + male Wixen gives Katress Ignis
  • male Katress + female Wixen gives Wixen Noct

Most special combos are unordered. This one is not.

If you store special combos in a map keyed by sorted parent names, both rows become the same key:

Katress|Wixen
Enter fullscreen mode Exit fullscreen mode

One row overwrites the other, and one child disappears from your reverse lookup.

The combo export avoids that by carrying gender fields:

{
  "parent_a": "Katress",
  "parent_a_gender": "female",
  "parent_b": "Wixen",
  "parent_b_gender": "male",
  "child": "Katress Ignis",
  "breeds_true": false,
  "gender_dependent": true
}
Enter fullscreen mode Exit fullscreen mode

If your tool builds a reverse planner, you need this.

Correction 2: farm eligibility is not the same as having a row

Some data rows exist because they are in the game files, but they do not mean the Pal can actually use the Breeding Farm.

Panthalus and Astralym are the two important cases in this dataset.

They have self-pair rows in the game data. A naive tool might read those rows and conclude that each Pal breeds true.

In practice, they cannot be used as normal breeding parents:

  • Panthalus cannot use base facilities, including the Breeding Farm.
  • Astralym is unobtainable by the player.

So the Pal export separates:

breedable
breeding_farm_eligible
Enter fullscreen mode Exit fullscreen mode

Those fields are not duplicates. A Pal can be present in the data while still being excluded from real parent-pair planning.

Correction 3: a self-pair row is not enough

This one was my own mistake.

I originally treated any X + X -> X row as proof that a Pal was catch-only.

That is too aggressive.

Relaxaurus Lux and Mossanda Lux have self-pair rows, but they also have real cross-species combos:

  • Relaxaurus + Sparkit
  • Mossanda + Grizzbolt

The correct rule is:

A Pal is catch-only only when every listed route for that Pal is the self-pair.

That bug is now in the corrections log because I want downstream users to know what changed and why.

The CombiRank formula still matters

The data is not just a table of special cases.

For ordinary breeding pairs, Palworld averages both parents' CombiRank, rounds up, and returns the closest Pal in the ordinary formula pool.

CombiRank runs opposite to player intuition: common Pals sit near the high end, rare Pals near the low end.

That is why the export includes the raw combi_rank instead of only a precomputed pair table. You can build your own planning logic if you want to rank routes differently.

For example, you might prefer parent pairs where the rarer parent is still relatively common:

function routeDifficulty(pair: [PalRow, PalRow]) {
  return Math.min(pair[0].combi_rank, pair[1].combi_rank);
}
Enter fullscreen mode Exit fullscreen mode

Higher is usually easier in that comparison, because the lower-ranked parent is less rare.

Why the corrections log is part of the product

Game datasets are not static truth.

They are interpreted. Sometimes the interpretation is wrong. Sometimes the source table is real but incomplete for gameplay. Sometimes a game update moves the goalposts.

That is why the data page includes a corrections log with:

  • what the common mistake is
  • what the actual behavior is
  • why the correction matters
  • the sources checked

This is not just for transparency. It is a maintenance tool. If someone tells me the calculator is wrong, I want to know which assumption changed.

Use it

The dataset license on the page is intentionally permissive:

Free to use, including commercially. Attribution with a link to palworldonline.net is appreciated.

If you are building a Palworld tool, spreadsheet, wiki helper, Discord bot, route planner, or visualization, you can start here:

https://www.palworldonline.net/data

If you only want the calculator, it is here:

https://www.palworldonline.net/

And if you find an error, please treat that as useful signal. I opened the data because I would rather have one corrected table than a dozen tools quietly repeating the same bug.

Top comments (1)

Collapse
 
launchgatecheck profile image
Launch Gate •

The gender-dependent collision would make a useful CSV/JSON parity fixture: load both exports, build the reverse lookup, and assert that both Katress/Wixen children survive. If parent order is normalized, the gender needs to travel with its parent rather than be sorted independently.

Do the Pal and combo exports carry a shared dataset revision? A cached Pal list from before a correction paired with newer combos could produce a plausible but inconsistent planner. A revision check plus fixtures for the two farm-ineligible entries would help downstream tools detect that mismatch. I haven't run the exports; these are checks suggested by the corrections you describe.