diff --git a/src/ppu.rs b/src/ppu.rs
index 995bfb27c34d2b3ed7a24bf5dddf5788ec61987d..1cd40a9fe18fe5fc17ecc91f4cab0a79a9517b41 100644
--- a/src/ppu.rs
+++ b/src/ppu.rs
@@ -144,6 +144,24 @@ impl PaletteInfo {
         }
     }
 
+    pub fn from_colors_hex(name: &str, colors_hex: &str) -> Self {
+        let colors = Self::parse_colors_hex(colors_hex);
+        Self::new(name, colors)
+    }
+
+    pub fn parse_colors_hex(colors_hex: &str) -> Palette {
+        let mut colors = [[0u8; RGB_SIZE]; PALETTE_SIZE];
+        for (index, color) in colors_hex.split(',').enumerate() {
+            let color = color.trim();
+            let color = u32::from_str_radix(color, 16).unwrap_or(0);
+            let r = ((color >> 16) & 0xff) as u8;
+            let g = ((color >> 8) & 0xff) as u8;
+            let b = (color & 0xff) as u8;
+            colors[index] = [r, g, b];
+        }
+        colors
+    }
+
     pub fn name(&self) -> &String {
         &self.name
     }
@@ -151,6 +169,24 @@ impl PaletteInfo {
     pub fn colors(&self) -> &Palette {
         &self.colors
     }
+
+    pub fn colors_hex(&self) -> String {
+        let mut buffer = String::new();
+        let mut is_first = true;
+        for color in self.colors.iter() {
+            let r = color[0];
+            let g = color[1];
+            let b = color[2];
+            let color = (r as u32) << 16 | (g as u32) << 8 | b as u32;
+            if is_first {
+                is_first = false;
+            } else {
+                buffer.push(',');
+            }
+            buffer.push_str(format!("{:06x}", color).as_str());
+        }
+        buffer
+    }
 }
 
 /// Represents a tile within the Game Boy context,
diff --git a/src/py.rs b/src/py.rs
index 87aadc16174436c7095a943a90439cd9435bb006..4b18b1a7aaa88640e99678cc4d9877c7759f6472 100644
--- a/src/py.rs
+++ b/src/py.rs
@@ -3,7 +3,7 @@ use pyo3::{prelude::*, types::PyBytes};
 use crate::{
     gb::{GameBoy as GameBoyBase, GameBoyMode},
     info::Info,
-    ppu::{DISPLAY_HEIGHT, DISPLAY_WIDTH},
+    ppu::{PaletteInfo, DISPLAY_HEIGHT, DISPLAY_WIDTH},
 };
 
 #[pyclass]
@@ -57,6 +57,11 @@ impl GameBoy {
         pybytes.into()
     }
 
+    pub fn set_palette_colors(&mut self, colors_hex: &str) {
+        let palette = PaletteInfo::from_colors_hex("default", colors_hex);
+        self.system.ppu().set_palette_colors(palette.colors());
+    }
+
     pub fn ppu_enabled(&self) -> bool {
         self.system.ppu_enabled()
     }
diff --git a/src/python/boytacean/__init__.py b/src/python/boytacean/__init__.py
index adc3074f27b2e94643011a0702886c5dc5b81953..1b4517ad7755dda1ef43ee65e4b43fa9675eddc5 100644
--- a/src/python/boytacean/__init__.py
+++ b/src/python/boytacean/__init__.py
@@ -1 +1,9 @@
-from .gb import *
+from .gb import (
+    DISPLAY_WIDTH,
+    DISPLAY_HEIGHT,
+    CPU_FREQ,
+    GameBoy,
+    GameBoyMode,
+    GameBoyRust,
+)
+from .palettes import PALETTES
diff --git a/src/python/boytacean/gb.py b/src/python/boytacean/gb.py
index 12c477c2db88b6800fcd823f50e4c9c2568f28b6..9451ffdbe3e8ddd62c2f9d159996b4d70c0bc9ad 100644
--- a/src/python/boytacean/gb.py
+++ b/src/python/boytacean/gb.py
@@ -2,6 +2,8 @@ from enum import Enum
 
 from PIL.Image import Image, frombytes
 
+from .palettes import PALETTES
+
 from .boytacean import DISPLAY_WIDTH, DISPLAY_HEIGHT, CPU_FREQ, GameBoy as GameBoyRust
 
 
@@ -76,6 +78,15 @@ This is a [Game Boy](https://en.wikipedia.org/wiki/Game_Boy) emulator built usin
         image = self.image()
         image.save(filename, format=format)
 
+    def set_palette(self, name: str):
+        if not name in PALETTES:
+            raise ValueError(f"Unknown palette: {name}")
+        palette = PALETTES[name]
+        self.set_palette_colors(palette)
+
+    def set_palette_colors(self, colors_hex: str):
+        self._system.set_palette_colors(colors_hex)
+
     @property
     def ppu_enabled(self) -> bool:
         return self._system.ppu_enabled()
diff --git a/src/python/boytacean/palettes.py b/src/python/boytacean/palettes.py
new file mode 100644
index 0000000000000000000000000000000000000000..7f11977727f4f0faa097f358e567ac328da613a8
--- /dev/null
+++ b/src/python/boytacean/palettes.py
@@ -0,0 +1,17 @@
+BASIC_PALETTE = "ffffff,c0c0c0,606060,000000"
+HOGWARDS_PALETTE = "b6a571,8b7e56,554d35,201d13"
+CHRISTMAS_PALETTE = "e8e7df,8bab95,9e5c5e,534d57"
+GOLDSILVER_PALETTE = "c5c66d,97a1b0,585e67,235229"
+PACMAN_PALETTE = "ffff00,ffb897,3732ff,000000"
+MARIOBROS_PALETTE = "f7cec3,cc9e22,923404,000000"
+POKEMON_PALETTE = "f87800,b86000,783800,000000"
+
+PALETTES = {
+    "basic": BASIC_PALETTE,
+    "hogwards": HOGWARDS_PALETTE,
+    "christmas": CHRISTMAS_PALETTE,
+    "goldsilver": GOLDSILVER_PALETTE,
+    "pacman": PACMAN_PALETTE,
+    "mariobros": MARIOBROS_PALETTE,
+    "pokemon": POKEMON_PALETTE,
+}