Skip to main content

Overview

Minecraft Web Client features comprehensive control support with fully customizable keybindings, gamepad support, and mobile touch controls. All controls are handled through the ControMax library with support for keyboard, mouse, and gamepad inputs.
Controls are configured in the game settings and stored in your browser’s local storage.

Default Keyboard Controls

Movement

W
key
Move forward
S
key
Move backward
A
key
Strafe left
D
key
Strafe right
Space
key
Jump / Swim upDouble-tap: Toggle flying (in Creative/Spectator)
Shift
key
Sneak / Descend while flying
Ctrl
key
SprintAlternative: Double-tap W to sprint
// Movement controls from src/controls.ts:46
commands: {
  movement: {
    forward: ['KeyW'],
    back: ['KeyS'],
    left: ['KeyA'],
    right: ['KeyD'],
    jump: ['Space', 'A'],
    sneak: ['ShiftLeft', 'Down'],
    sprint: ['ControlLeft', 'Left Stick'],
  }
}

Actions

Left Click
mouse
Attack / Break block
Right Click
mouse
Use item / Place block / Interact
Middle Click
mouse
Pick block (Creative mode)Copies the block you’re looking at to your hotbar
Mouse Wheel
mouse
Cycle through hotbar slots
1-9
keys
Select hotbar slot 1-9
// Mouse controls from src/controls.ts:826
addEventListener('mousedown', async (e) => {
  if (!isInRealGameSession()) return
  void pointerLock.requestPointerLock()
  
  // Middle click - pick block
  if (e.button === 1) {
    await selectItem()
  }
})

Inventory & Interaction

E
key
Open/close inventory
Q
key
Drop item (single item from stack)
Ctrl+Q
key
Drop entire stack
F
key
Swap items between hands
H
key
Select item (pick block in Creative)

Communication

T
key
Open chat
Enter
key
Open chat (alternative)
/
key
Open chat with / prefix (command mode)
Tab
key
Hold: Show player list
M
key
Toggle microphone (voice chat)

Camera & View

F5
key
Cycle perspective (First person → Third person back → Third person front)
C
key
Zoom (OptiFine-style)
F1
key
Toggle UI visibility
F2
key
Take screenshotSaves to downloads folder as PNG
// Screenshot functionality from src/controls.ts:871
window.addEventListener('keydown', (e) => {
  if (e.code !== 'F2' || e.repeat || !isGameActive(true)) return
  e.preventDefault()
  
  const canvas = document.getElementById('viewer-canvas') as HTMLCanvasElement
  const link = document.createElement('a')
  link.href = canvas.toDataURL('image/png')
  const date = new Date()
  link.download = `screenshot ${date.toLocaleString()}.png`
  link.click()
})

System & Interface

Esc
key
  • In game: Pause menu
  • In menu: Go back / Close
  • Ctrl+Esc: Close all modals
F11
key
Toggle fullscreen
J
key
Toggle full-screen minimap
`
key
Toggle viewer console (debug)

Camera Controls

The client supports multiple camera control methods:

Mouse Camera

Pointer Lock mode (default):
  • Click the game to lock mouse pointer
  • Move mouse to rotate camera
  • Smooth, responsive rotation
  • Supports Raw Input mode
Raw Input (options.rawInput) disables mouse acceleration for precise aiming. Recommended for all platforms, enabled by default.
// Raw input support from TECH.md:56
// requestPointerLock({ unadjustedMovement: true }) API
// Disables system mouse acceleration (important for Mac users)

Keyboard Camera Rotation

Rotate camera using keyboard (useful for accessibility):
Arrow Keys
keys
Rotate camera (when bound in settings)Default: Not bound (customizable)
// Keyboard rotation from src/controls.ts:225
const cameraRotationControls = {
  movements: {
    left: { movementX: -0.5, movementY: 0 },
    right: { movementX: 0.5, movementY: 0 },
    up: { movementX: 0, movementY: -0.5 },
    down: { movementX: 0, movementY: 0.5 }
  },
  config: {
    speed: 1, // movement per interval
    interval: 5 // ms between movements
  }
}
Bind in settings:
  • general.rotateCameraLeft
  • general.rotateCameraRight
  • general.rotateCameraUp
  • general.rotateCameraDown

Camera Perspectives

Cycle with F5:
Default view - see from player’s eyes
// Perspective switching from src/controls.ts:388
case 'general.togglePerspective':
  if (pressed) {
    const currentPerspective = playerState.reactive.perspective
    switch (currentPerspective) {
      case 'first_person':
        playerState.reactive.perspective = 'third_person_back'
        break
      case 'third_person_back':
        playerState.reactive.perspective = 'third_person_front'
        break
      case 'third_person_front':
        playerState.reactive.perspective = 'first_person'
        break
    }
  }
  break

Gamepad Support

Full Xbox/PlayStation controller support with customizable button mappings.

Default Gamepad Layout

Movement

Left Stick: MoveRight Stick: Look aroundClick Left Stick: SprintClick Right Stick: Toggle sneak

Actions

A Button: Jump / Select (UI)B Button: Drop item / Back (UI)X Button: Inventory / Confirm (UI)Y Button: (Customizable)

Triggers

Right Trigger: Attack/BreakLeft Trigger: Use/PlaceRight Bumper: Next hotbar slotLeft Bumper: Previous hotbar slot

Special

D-Pad Up: Toggle perspectiveD-Pad Down: SneakD-Pad Left: Player listD-Pad Right: ChatStart: Pause menu
// Gamepad configuration from src/controls.ts:44
commands: {
  movement: {
    forward: ['KeyW'],
    back: ['KeyS'],
    left: ['KeyA'],
    right: ['KeyD'],
    jump: ['Space', 'A'], // Keyboard, Gamepad
    sneak: ['ShiftLeft', 'Down'],
    toggleSneakOrDown: [null, 'Right Stick'],
    sprint: ['ControlLeft', 'Left Stick'],
  },
  general: {
    inventory: ['KeyE', 'X'],
    drop: ['KeyQ', 'B'],
    attackDestroy: [null, 'Right Trigger'],
    interactPlace: [null, 'Left Trigger'],
    nextHotbarSlot: [null, 'Right Bumper'],
    prevHotbarSlot: [null, 'Left Bumper'],
  }
}
Gamepad polling runs at 10ms intervals for responsive input.

UI Navigation with Gamepad

  • A: Select / Left click
  • B: Back / Cancel
  • X: Right click (context menu)
  • Left Stick (Click): Speed up cursor movement

F3 Debug Controls

Advanced debug shortcuts accessed with F3 + key:
F3
key
Toggle debug overlay (FPS, coordinates, chunk info)
F3+A
key
Reload all chunksUseful when chunks appear corrupted or incomplete
F3+G
key
Toggle chunk borders and entity outlines
  • Yellow: Chunk sections
  • Red: Hostile mobs
  • Green: Passive mobs
  • Blue: Players
F3+H
key
Show chunks debug menu
F3+T
key
Reload texturesReloads resource pack textures
F3+Y
key
Open widget menuAccess minimap, waypoints, and other widgets
F3+P
key
Show player and ping detailsDisplays:
  • Player UUID
  • Current ping to server
  • Proxy server latency
F3+F4
key
Cycle game modeCreative → Survival → Adventure → Spectator
// F3 keybinds from src/controls.ts:628
export const f3Keybinds = [
  {
    key: 'KeyA',
    action() {
      // Reload all chunks
      worldView.unloadChunk(/* all chunks */)
      void reloadChunks()
    },
    mobileTitle: 'Reload chunks',
  },
  {
    key: 'KeyG',
    action() {
      options.showChunkBorders = !options.showChunkBorders
    },
    mobileTitle: 'Toggle chunk borders',
  },
  {
    key: 'F4',
    async action() {
      // Cycle through game modes
      let nextGameMode: GameMode
      switch (bot.game.gameMode) {
        case 'creative': nextGameMode = 'survival'; break
        case 'survival': nextGameMode = 'adventure'; break
        case 'adventure': nextGameMode = 'spectator'; break
        case 'spectator': nextGameMode = 'creative'; break
      }
      bot.chat(`/gamemode ${nextGameMode}`)
    },
    mobileTitle: 'Cycle Game Mode'
  },
]

Customizing Keybindings

All keybindings are fully customizable through the settings menu.

Accessing Keybindings

1

Open Settings

Press EscOptions (or Settings)
2

Controls Section

Navigate to Controls or Keybindings
3

Customize

Click any action to rebind it
  • Press the desired key/button
  • Supports multiple bindings per action
  • Separate keyboard and gamepad bindings
4

Save

Changes are automatically saved to browser storage

Keybinding Storage

Keybindings are stored in local storage and synced via Valtio:
// Keybindings storage from src/controls.ts:35
export const customKeymaps = proxy(appStorage.keybindings)
subscribe(customKeymaps, () => {
  appStorage.keybindings = customKeymaps
})

// Update bindings dynamically
export function updateBinds(commands: any) {
  for (const [group, actions] of Object.entries(commands)) {
    contro.userConfig![group] = Object.fromEntries(
      Object.entries(actions).map(([key, value]) => {
        return [key, {
          keys: value?.keys ?? undefined,
          gamepad: value?.gamepad ?? undefined,
        }]
      })
    )
  }
}
Your keybindings are preserved across sessions and browser restarts.

Keyboard Layout Support

Chromium browsers only: The client uses navigator.keyboard.getLayoutMap() to display the correct key symbols for different keyboard layouts (QWERTY, AZERTY, etc.).
// From TECH.md:58
// navigator.keyboard.getLayoutMap()
// To display the right keyboard symbol for the key keybinding
// on different keyboard layouts (e.g. QWERTY vs AZERTY)

Special Control Modes

Flying Controls

In Creative or Spectator mode:
Space
key
Fly upward
Shift
key
Fly downward
Double-tap Space
key
Toggle flying on/off
// Flying toggle from src/controls.ts:797
const toggleFly = (newState = !isFlying(), sendAbilities?: boolean) => {
  if (!bot.entity.canFly) return
  
  if (newState) {
    bot._client.write('abilities', { flags: 2 })
    (bot.entity as any).flying = true
  } else {
    bot._client.write('abilities', { flags: 0 })
    (bot.entity as any).flying = false
  }
}

Spectator Mode

Additional controls when spectating:
  • Click on entity: Spectate that entity
  • Shift+F5: Exit entity spectating
  • Fly through blocks
  • No collision detection

Control Settings

From the README, these settings improve control experience:
Controls → Raw Input → OnMakes camera controls more precise by disabling mouse acceleration.
Especially important for Mac users!
Controls → Touch Controls Type → JoystickBetter mobile experience with virtual joystick.
Controls → Auto Full Screen → OnPrevents accidental Ctrl+W (close window) during gameplay.

Advanced Control Options

Access via browser console:
// View all control options
options

// Modify control settings
options.rawInput = true
options.mouseSensitivity = 1.5
options.autoFullscreen = true

// View current controller state
contro.pressedKeys // Currently pressed keys
contro.userConfig // Current keybinding configuration

Mobile Touch Controls

See Mobile & Touch Support for comprehensive touch control documentation, including:
  • Virtual joysticks
  • Touch buttons
  • Gesture controls
  • Mobile-specific optimizations

Controller Support

See Controller Support for detailed gamepad configuration, including:
  • Button remapping
  • Stick sensitivity
  • Trigger customization
  • Multiple controller support

Browser-Specific Features

Chromium Browsers (Chrome, Edge, Brave)

Keyboard Lock

navigator.keyboard.lock() in fullscreenAllows using Ctrl+W, Ctrl+T, etc. in-game

Layout Detection

navigator.keyboard.getLayoutMap()Shows correct key symbols for your layout

All Browsers

Pointer Lock

requestPointerLock({ unadjustedMovement: true })Raw mouse input for precise camera control

Troubleshooting

Cause: Game window not focused or pointer not lockedSolutions:
  • Click on the game canvas
  • Check if pointer lock is active
  • Reload the page
Cause: Mouse sensitivity settingSolutions:
  • Adjust in Settings → Controls → Mouse Sensitivity
  • Try enabling/disabling Raw Input
  • Check system mouse settings
Cause: Gamepad not connected or browser doesn’t supportSolutions:
  • Ensure gamepad is properly connected
  • Press any button to activate gamepad
  • Check browser gamepad API support
  • Try Chrome/Edge for best compatibility
Cause: Multiple actions bound to same keySolutions:
  • Review keybindings in Settings
  • Reset to defaults if needed
  • Clear browser storage and reconfigure
Cause: Mouse gestures interfering with controlsSolutions:
  • Disable Raw Input in game settings
  • Disable mouse gestures in Vivaldi settings
Cause: Mouse gestures opening new tabs on right-clickSolutions:
  • Disable mouse gestures in Opera settings

Command Reference

See Keybindings Reference for a complete, printable list of all keybindings.

Build docs developers (and LLMs) love