Skip to content

Repository files navigation

PalDex

A live, self-hosted map for a Palworld dedicated server — player positions, collectibles, bosses, and world state, almost all read straight from the server's own save files and the game's own assets. A small handful of values that aren't stored anywhere in the game's own data are cross-checked against public wikis instead — see below for exactly which ones.

Map overview

What it shows

Layer What it tracks Live per-player state?
Players Live position, level, HP, hunger, online/offline (via RCON), last-online time
Effigies (Relics) 407 collectible statues, grouped by tier ✅ per-player collected
Alpha Bosses 90 field-boss spawns, name/species/element ✅ per-player defeated
Bounty 33 named human NPC bosses (bandit/raider/syndicate leaders) ✅ per-player defeated
Challenge Towers The 9 "GYM" boss-rush towers ✅ per-player defeated
Oil Rigs The 3 raid-zone POIs world-shared (no per-player state exists)
Watchtowers / Waypoints 22 climbable watchtowers + 152 fast-travel points ✅ per-player unlocked
Journals 64 lore pickups (Castaway's Journal + NPC Diaries) ✅ per-player read
Schematics 106 blueprint pickups ✅ per-player collected
NPCs 104 named NPCs (General/Wandering Merchant/Pal Dealer/Black Market/Dog Coin), with a shop-inventory modal (items or capturable Pals, live price/pool where the game exposes one)
Quests 87 quests with a map location (28 Main, 59 Sub), split into Active/Not Started ✅ per-player, shown only once a player is selected
Guild Bases Player-built bases, grouped by guild live, world-shared
Dungeons Open-world dungeon entrances — only the ones currently spawned/enterable are shown, with a live active / total count and a despawn ETA. Click one for a full contents modal: every Boss/Mid-Boss/Normal/Monster/Fish/Human-Enemy tier, each marked Guaranteed or Random pool (N possible), boss escorts folded into a "w/ Escorts" flag instead of cluttering the grid, real portraits for every enemy including the human factions live, world-shared
Pal Spawns Wild-Pal field spawn locations as opt-in highlighted map regions (not a heatmap) — strictly regular wild Pals, never Alpha Bosses/dungeon spawns/human NPCs. Defaults to nothing shown; pick a species and its actual spawn radius lights up, along with a spinning rainbow ring calling out that species' Alpha Boss (if it has one) and any currently-active dungeon it can be found in ✅ per-player Mimog Effigy capture progress (✓/N-of-5)

The sidebar groups everything above into five collapsible categories — Points of Interest, Collectibles, Combat, Quests (only shows content once a player is picked, since quest progress is inherently per-player), and Pal Spawns (the one category that stays empty until you actively pick a species, for the reason above) — and remembers which sections/checkboxes you had expanded/checked, plus your View As pick, across a page refresh (localStorage, client-side only — nothing server-side is saved per visitor).

Selecting a player from View As... filters every checklist to what that player has actually collected/defeated/unlocked, and pans the map to their current position — here's Cat, zoomed to her own position, with her own per-player checkmarks (and Mimog Effigy capture progress) applied across every relevant section:

View As example, zoomed to a specific player

Legend sidebar

Marker detail closeup


Clicking a Dungeon opens its full contents — which tiers are a guaranteed single enemy versus a genuine weighted pool, and a boss's escorts folded into a "w/ Escorts" flag instead of cluttering the grid with duplicate cards:

Dungeon Contents modal

Pal Spawns is opt-in on purpose — nothing shows until you pick a species (checking everything at once would just highlight the whole map). Selecting one lights up its real spawn radius, plus a spinning rainbow ring calling out that species' Alpha Boss and any dungeon that's currently spawned with it inside:

Pal Spawns sidebar, searchable species list with Mimog Effigy progress

Pal Spawns highlighted region with an Alpha Boss call-out ring


How it works

  • backend/remote.py pulls Level.sav and every player's .sav from the dedicated server host over SSH (sudo-scoped rsync/SFTP), on a 30-second refresh loop. This project runs against AMP, but nothing about it actually depends on AMP — see deploy/README.md/ deploy/bare-metal.md for pointing it at a bare PalServer install instead.
  • backend/parse.py decodes the save files using deafdudecomputers/PalworldSaveTools (the PyPI palworld-save-tools package doesn't support the 1.0 release's save format) and extracts everything live: player state, per-player collection/defeat/unlock flags, guild bases, which dungeon entrances currently have a spawned instance, and — as of Pal Spawns — each species' lifetime capture count (PalCaptureCount), which is what actually determines Mimog Effigy progress.
  • extractor/PalExtract is a one-off C# console app (CUE4Parse) that reads the static data (positions, names, icons, element types, map textures, and — for Dungeon Contents/Pal Spawns — full enemy rosters joined from the game's own spawner/loot tables) directly out of the game's own .uasset/World Partition files. This runs once per game patch on a Windows box with the game installed, not at request time — its output is baked into the Docker image as data/*_static.json + frontend/assets/.
  • backend/server.py is a Flask app that serves the static + live data as JSON (/api/players, /api/relics, /api/dungeons, /api/dungeon_contents, /api/pal_spawn_locations, etc.).
  • frontend/index.html is a single-page Leaflet (CRS.Simple) map, rendered against the game's own map texture, polling those endpoints — no build step, no framework.

Nothing here is guessed: every mechanic (effigy collection flags, boss kill-tracking keys, dungeon active-state, coordinate transforms, etc.) was reverse-engineered directly from a real save file or the game's own data tables, with dead ends recorded so they don't get re-attempted. A short list of values simply don't exist anywhere in the game's own files, and for those we cross-check public wikis instead:

  • Elemental type-effectiveness chart — baked into UI Blueprint logic (WBP_MainMenu_Pal_ElementMatchup), not a DataTable, so it can't be extracted. Sourced from the publicly documented chart, cross-checked against game8.co and dexerto.com for agreement, then sanity-checked against a real Pal's known matchups.
  • Challenge Tower HUD coordinates and recommended levels — no data-mined "recommended level" or reliable overworld position exists for towers in the game's own tables. Sourced from real in-game HUD coordinates read off the map, independently cross-checked against palworld.fandom.com's Tower page for agreement.
  • Wandering Merchant / Pal Dealer positions, and real quest display names — these NPCs are wild-spawns with no placement data anywhere in the game's own files (confirmed dead end after an exhaustive search), and QuestTitleMsgId doesn't resolve through any shipped DataTable or StringTable either. Both are sourced from palpedia.ru, a data-mined community Palworld database, spot-checked against real in-game reports before trusting it for the rest.

The full investigation log — including how each of these was verified, and a wiki-sourced typo that was caught and corrected along the way — lives in NOTES.md.

Tech stack

Backend Python 3.13, Flask
Save parsing palsav-flex / palooz (Oodle decompression)
Frontend Leaflet.js, vanilla JS, no build step
Extractor C#, .NET, CUE4Parse
Deployment Docker/Portainer (git-repository stack), or bare Linux (systemd)

Acknowledgments

This project reads almost all of its data directly from the game itself rather than scraping a wiki (see "How it works" above for the handful of wiki-sourced exceptions), which wouldn't be possible without these open-source projects:

  • deafdudecomputers/PalworldSaveTools — save file decoding (palsav-flex, palooz), including Oodle/PlM decompression for the 1.0 game release. Does all the heavy lifting behind every "live" layer on the map.
  • FabianFG/CUE4Parse + CUE4Parse-Conversion — reads Unreal Engine assets (.uasset/World Partition/DataTables) directly, powering extractor/PalExtract's extraction of every static position, name, icon, and map texture.
  • SixLabors.ImageSharp — image resizing for the extracted icon set (a CUE4Parse-Conversion dependency, used directly for downscaling Journal icons).
  • PalworldModding/UsefulFiles — actively-maintained CUE4Parse mapping files for the current game version.
  • palworldlol/palworld-coord — the in-game-HUD-coordinate conversion formula used to validate several extracted positions (see NOTES.md).
  • Leaflet — the map renderer this whole frontend is built on.

Running locally

This is the Windows dev-box flow (uses the Bitvise SSH Client for the save-file pull — see backend/remote.py). For Linux, including a bare LXC/VM with no Docker, use deploy/bare-metal.md instead — the setup differs enough (OpenSSH key provisioning, an env var with no default outside a container, a Python import gotcha in how you invoke server.py) that it's not just a pip install away.

cd backend
python -m venv ../.venv
../.venv/Scripts/pip install -r requirements.txt
cp secrets.py.example secrets.py
# edit secrets.py and fill in RCON_PASSWORD / AMP_HOST / AMP_USER /
# AMP_SAVE_ROOT / AMP_WORLD_GUID (or set them as env vars instead --
# those take priority if both are set)
python server.py

Then open http://localhost:5151.

Whichever platform you're on, always run server.py directly as a script (python server.py / python backend/server.py), never as a module (python -m backend.server) or via a WSGI target (backend.server:app). The config loader (backend/config.py) resolves backend/secrets.py via a plain import secrets — that only finds this project's file if backend/ is the directory Python was launched from (true for python server.py/python backend/server.py, false for -m invocation). Get it wrong and Python silently imports its own standard library secrets module instead, which has no RCON_PASSWORD attribute — producing a "not set" error that looks like a missing-config problem, not an import-shadowing one.

Deploying

Two supported paths:

  • Docker/Portainer — see deploy/README.md (required env vars, SSH key provisioning, and gotchas from the first real deploy).
  • Bare Linux LXC/VM, no Docker — see deploy/bare-metal.md (same config, plus the container-only defaults and import gotchas above that don't apply once there's no container around it).

Project layout

backend/            Flask app, save-file parsing, live refresh loop
frontend/            Leaflet map (index.html + assets/)
extractor/PalExtract  One-off CUE4Parse extractor for static game data
data/                 Static extracted JSON (+ gitignored live-refreshed data)
deploy/               Docker/Portainer + bare-metal deployment docs and config
docs/                 README screenshots
NOTES.md              Full reverse-engineering investigation log

License

MIT

About

Live self-hosted map for a Palworld dedicated server — players, collectibles, bosses, and world state read straight from the game's own save files and assets.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages