Skip to main content

Overview

Minecraft Web Client supports loading worlds from multiple sources, including ZIP archives and local folders. All world formats compatible with Minecraft Java Edition work seamlessly.
Worlds are loaded entirely in your browser using the integrated Flying Squid server and Prismarine Provider Anvil for region file handling.

Supported Formats

ZIP Files

  • Entire world compressed in a single file
  • Stored in browser RAM
  • ~300 MB limit on iOS
  • Read-only by default

Folders

  • Native folder access via File System API
  • Read-only or read-write mode
  • Better for large worlds
  • Chrome/Edge only

Loading Methods

Drag and Drop

The easiest way to load a world:
1

Prepare Your World

Ensure your world is either:
  • A ZIP file containing level.dat and region/ folder
  • A folder with standard Minecraft world structure
2

Drag to Browser

Simply drag the ZIP file or folder into the browser window while on the game page.
3

Select Mode (Folders Only)

For folders, choose:
  • Read-only: Safe, no modifications to original files
  • Read-write: Full editing capability, changes saved to folder
4

World Loads

The world will load automatically using the detected or selected version.
When opening folders in read-write mode, ensure you have a backup! New chunks may be generated incorrectly.

URL Parameters

Load a world from a ZIP file URL:
?map=https://example.com/world.zip
The URL must be CORS-enabled for the browser to access it.
Example CORS headers needed:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET

Via File System API

// World loading implementation from src/loadSave.ts
export const loadSave = async (root = '/world', connectOptions?: Partial<ConnectOptions>) => {
  // Read level.dat to detect version
  const { levelDat, dataRaw } = (await readLevelDat(root))!
  
  // Extract version information
  let version = levelDat.Version?.Name
  if (!version) {
    // Fallback for 1.8 and earlier
    version = '1.8.8'
  }
  
  // Handle player data override
  const playerUuid = nameToMcOfflineUUID(options.localUsername)
  const playerDatPath = `${root}/playerdata/${playerUuid}.dat`
  
  // Dispatch singleplayer event
  window.dispatchEvent(new CustomEvent('singleplayer', {
    detail: { version, worldFolder: root, connectOptions }
  }))
}

File Limits and Memory

ZIP Files

iOS Limitation: ~300 MB maximum file sizeThis is due to browser memory constraints on mobile devices.
Desktop browsers: Can typically handle ZIP files up to several GB, depending on available RAM.
When loading ZIP files:
  • Entire world is decompressed into memory
  • Larger worlds = longer load times
  • Consider using folder access for worlds >500 MB
// Zip files stored in RAM from README.MD:74
// When opening zip files, they are stored entirely in your RAM.
// There is a ~300 MB file limit on iOS.

Folder Access

No file size limits when using folder access:
  • Files read on-demand
  • Only loaded chunks kept in memory
  • Better performance for large worlds
Folder access requires the File System Access API, available in:
  • Chrome 86+
  • Edge 86+
  • Not available in Firefox or Safari

World Structure

A valid Minecraft world folder must contain:
world/
├── level.dat          # World metadata (required)
├── region/            # Terrain data (required)
│   ├── r.-1.-1.mca
│   ├── r.-1.0.mca
│   ├── r.0.-1.mca
│   └── r.0.0.mca
├── playerdata/        # Player data files
│   └── <uuid>.dat
├── data/              # Scoreboard, structures, etc.
└── DIM-1/             # Nether dimension (optional)
    └── region/

level.dat Detection

// From src/loadSave.ts:37
export const readLevelDat = async (path) => {
  let levelDatContent
  try {
    levelDatContent = await fs.promises.readFile(`${path}/level.dat`)
  } catch (err) {
    if (err.code === 'ENOENT') {
      return undefined // level.dat not found
    }
    throw err
  }
  
  const { parsed } = await nbt.parse(Buffer.from(levelDatContent))
  const levelDat = nbt.simplify(parsed).Data
  return { levelDat, dataRaw: parsed.value.Data!.value }
}
If level.dat is missing:
  • Read-only mode: Error - cannot load world
  • Read-write mode: Warning - new world will be created in folder

Version Detection

The client automatically detects world version from level.dat:
// Version detection from src/loadSave.ts:88
let version = levelDat.Version?.Name
if (!version) {
  // For Minecraft 1.8 and earlier
  // level.dat doesn't contain version info
  const newVersion = '1.8.8'
  version = newVersion
}

Version Override

Force a specific version:
?loadSave=my-world&version=1.19.4
or for URL maps:
?map=https://example.com/world.zip&mapVersion=1.20.1

Exporting Worlds

Save your progress by exporting the world back to your computer.

Export Command

Use the /export or /download command in chat:
1

Save First

/save
Ensures all changes are persisted.
2

Export

/export
or
/download
3

Wait for Generation

You’ll see: “Generating zip, this may take a few minutes”
Do not close the browser during export!
4

Download Starts

Your browser downloads world-prismarine-exported.zip
// Export implementation from src/builtinCommands.ts:36
export const exportWorld = async (path: string, type: 'zip' | 'folder', zipName = 'world-prismarine-exported') => {
  try {
    if (type === 'zip') {
      setLoadingScreenStatus('Generating zip, this may take a few minutes')
      const zip = new JSZip()
      await addFolderToZip(path, zip, '')
      
      // Generate the ZIP archive content
      const zipContent = await zip.generateAsync({ type: 'blob' })
      
      // Create a download link and trigger the download
      const downloadLink = document.createElement('a')
      downloadLink.href = URL.createObjectURL(zipContent)
      downloadLink.download = `${zipName}.zip`
      downloadLink.click()
      
      URL.revokeObjectURL(downloadLink.href)
    }
  } finally {
    setLoadingScreenStatus(undefined)
  }
}

Export to Folder

For folder-based saves with write access, worlds are automatically saved in place. Use the /export command to create a separate copy:
// Folder export from src/builtinCommands.ts:55
if (type === 'folder') {
  setLoadingScreenStatus('Preparing export folder')
  let dest = '/'
  if ((await fs.promises.readdir('/export')).length) {
    const { levelDat } = (await readLevelDat(path))!
    dest = await uniqueFileNameFromWorldName(levelDat.LevelName, path)
  }
  await copyFilesAsync(path, '/export' + dest)
}

Saving Behavior

Automatic Saves

Worlds are automatically saved:
  • Every few minutes during gameplay
  • On disconnect/world exit
  • When using /save command
For ZIP and URL-loaded worlds, use /export to download changes. They’re saved to browser memory, not the original file.

Disable Auto-Save

Prevent automatic saving:
?noSave=true
With this option:
  • Only manual /save commands work
  • No save on disconnect
  • No periodic saves
  • Useful for testing without cluttering browser storage
// From README.MD:194
// ?noSave=true - Disable auto save on unload / disconnect / export
// Only manual save with `/save` command will work

Read-Only vs Read-Write

Characteristics:
  • Original files never modified
  • Changes stored in browser memory
  • Safe for preserving original worlds
  • Use /export to save changes
When to use:
  • Exploring downloaded worlds
  • Testing without risk
  • iOS devices (no folder write access)
// FS state tracking from src/loadSave.ts:18
export const fsState = proxy({
  isReadonly: false,
  syncFs: false,
  inMemorySave: false,
  saveLoaded: false,
  openReadOperations: 0,
  openWriteOperations: 0,
  remoteBackend: false,
  inMemorySavePath: ''
})

Compatibility Notes

Some community worlds use non-standard folder structures. The client automatically handles:
// From src/loadSave.ts:147
const rootRemapFiles = ['Warp files']
for (const rootRemapFile of rootRemapFiles) {
  if (await existsViaStats(path.join(root, '..', rootRemapFile))) {
    forceRedirectPaths[path.join(root, rootRemapFile)] = path.join(root, '..', rootRemapFile)
  }
}
This ensures worlds with custom folder mappings load correctly.
Worlds from Minecraft 1.8 and before don’t store version information in level.dat.The client defaults to 1.8.8 but you should specify the correct version:
?loadSave=old-world&version=1.8.8
Worlds from modded Minecraft may contain:
  • Custom blocks (rendered as default textures)
  • Mod-specific data (ignored)
  • Non-standard chunk data (may cause errors)
Vanilla-only world saves are recommended for best compatibility.
For worlds larger than 1 GB:
  • Use folder access instead of ZIP
  • Increase render distance gradually
  • Monitor browser memory usage
  • Export frequently to prevent data loss

Debugging

Access world data in the browser console:
// View current world state
fsState

// Check if world is read-only
fsState.isReadonly

// View save path
fsState.inMemorySavePath

// Access level.dat data
readLevelDat('/world').then(console.log)
See Global Variables for more debugging tools.

Best Practices

Backup Regularly

Use /export frequently, especially before:
  • Major building projects
  • Exploring new chunks
  • Closing the browser

Version Consistency

Load worlds with their native version when possible:
?loadSave=my-119-world&version=1.19.4

Test Read-Only First

Always test with read-only mode before using read-write.

Monitor Memory

Watch browser memory usage for large worlds:
  • Chrome: Task Manager (Shift+Esc)
  • Firefox: about:memory

Build docs developers (and LLMs) love