diff --git a/CHANGELOG.md b/CHANGELOG.md
index e5b366bdfa8871e8e526cb649c8663f8ee2fc46b..427b8165068bda23b3ac904009ba08af9435cb5a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,15 @@ current (development)
 - Feature: `input` is now supporting multiple lines.
 - Feature: `input` style is now customizeable.
 
+### Dom
+- Feature: Add `hyperlink` decorator. For instance:
+  ```cpp
+  auto link = text("Click here") | hyperlink("https://github.com/FTXUI")
+  ```
+  See the [OSC 8 page](https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda).
+  FTXUI support proposed by @aaleino in [#662](https://github.com/ArthurSonzogni/FTXUI/issues/662).
+
+
 ### Build
 - Check version compatibility when using cmake find_package()
 - Add `FTXUI_DEV_WARNING` options to turn on warnings when building FTXUI
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c99700f8f18771a3a2a53d2249e01a638f640166..ebed83effa99af28215b2b9198c571aafe93e35b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -55,6 +55,7 @@ add_library(dom
   src/ftxui/dom/automerge.cpp
   src/ftxui/dom/blink.cpp
   src/ftxui/dom/bold.cpp
+  src/ftxui/dom/hyperlink.cpp
   src/ftxui/dom/border.cpp
   src/ftxui/dom/box_helper.cpp
   src/ftxui/dom/box_helper.hpp
diff --git a/README.md b/README.md
index 4abdb48f0532d042a61c61423d98d25dfe822f1e..763391d75a141003aa649bbf7956d46fcb7096ec 100644
--- a/README.md
+++ b/README.md
@@ -117,6 +117,7 @@ An element can be decorated using the functions:
   - `strikethrough`
   - `color`
   - `bgcolor`
+  - `hyperlink`
 
 [Example](https://arthursonzogni.github.io/FTXUI/examples_2dom_2style_gallery_8cpp-example.html)
 
diff --git a/cmake/ftxui_test.cmake b/cmake/ftxui_test.cmake
index 6142d5f69f489bb97b58cd6eda5f7228a4828d30..4c1b15a612b557a1b38ae7e7c4dd349c9a2b8596 100644
--- a/cmake/ftxui_test.cmake
+++ b/cmake/ftxui_test.cmake
@@ -36,6 +36,7 @@ add_executable(ftxui-tests
   src/ftxui/dom/gauge_test.cpp
   src/ftxui/dom/gridbox_test.cpp
   src/ftxui/dom/hbox_test.cpp
+  src/ftxui/dom/hyperlink_test.cpp
   src/ftxui/dom/linear_gradient_test.cpp
   src/ftxui/dom/scroll_indicator_test.cpp
   src/ftxui/dom/separator_test.cpp
diff --git a/examples/dom/CMakeLists.txt b/examples/dom/CMakeLists.txt
index ad3285e9ea9ef01c0aeaef7089b6ab75b61b2265..911bf7fe482c250baa0ca86c451e5ac6abaa779e 100644
--- a/examples/dom/CMakeLists.txt
+++ b/examples/dom/CMakeLists.txt
@@ -27,6 +27,7 @@ example(style_bold)
 example(style_color)
 example(style_dim)
 example(style_gallery)
+example(style_hyperlink)
 example(style_inverted)
 example(style_strikethrough)
 example(style_underlined)
diff --git a/examples/dom/style_gallery.cpp b/examples/dom/style_gallery.cpp
index c958c5745fdfb997e2727d0d166ee40d112c9a1f..419f29454ad4f86e039fb11e7886ce20522b6e69 100644
--- a/examples/dom/style_gallery.cpp
+++ b/examples/dom/style_gallery.cpp
@@ -19,7 +19,8 @@ int main() {
       text("blink")              | blink                , text(" ") ,
       text("strikethrough")      | strikethrough        , text(" ") ,
       text("color")              | color(Color::Blue)   , text(" ") ,
-      text("bgcolor")            | bgcolor(Color::Blue) ,
+      text("bgcolor")            | bgcolor(Color::Blue) , text(" ") ,
+      text("hyperlink")          | hyperlink("https://github.com/ArthurSonzogni/FTXUI"),
     });
   // clang-format on
   auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
diff --git a/examples/dom/style_hyperlink.cpp b/examples/dom/style_hyperlink.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8ab092c04f3992361ae583a7b011590f29bd61d5
--- /dev/null
+++ b/examples/dom/style_hyperlink.cpp
@@ -0,0 +1,25 @@
+#include <ftxui/dom/elements.hpp>  // for text, operator|, bold, Fit, hbox, Element
+#include <ftxui/screen/screen.hpp>  // for Full, Screen
+#include <memory>                   // for allocator
+
+#include "ftxui/dom/node.hpp"      // for Render
+#include "ftxui/screen/color.hpp"  // for ftxui
+
+int main() {
+  using namespace ftxui;
+  auto document =  //
+      hbox({
+          text("This text is an "),
+          text("hyperlink") | hyperlink("https://www.google.com"),
+          text(". Do you like it?"),
+      });
+  auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
+  Render(screen, document);
+  screen.Print();
+
+  return 0;
+}
+
+// Copyright 2020 Arthur Sonzogni. All rights reserved.
+// Use of this source code is governed by the MIT license that can be found in
+// the LICENSE file.
diff --git a/include/ftxui/dom/elements.hpp b/include/ftxui/dom/elements.hpp
index b414c76314c4046e964fd2a977b3ccf42a641500..d343cdc1d45b9669407cdd1e37568103bb0b1a6f 100644
--- a/include/ftxui/dom/elements.hpp
+++ b/include/ftxui/dom/elements.hpp
@@ -109,6 +109,8 @@ Element bgcolor(const LinearGradient&, Element);
 Decorator focusPosition(int x, int y);
 Decorator focusPositionRelative(float x, float y);
 Element automerge(Element child);
+Decorator hyperlink(std::string link);
+Element hyperlink(std::string link, Element child);
 
 // --- Layout is
 // Horizontal, Vertical or stacked set of elements.
diff --git a/include/ftxui/screen/screen.hpp b/include/ftxui/screen/screen.hpp
index d8a5329db2747ce8e78404b633aec5b5b6f3eacc..0bb90a8499844bd7ec503a156a8e32ea84122c46 100644
--- a/include/ftxui/screen/screen.hpp
+++ b/include/ftxui/screen/screen.hpp
@@ -1,8 +1,9 @@
 #ifndef FTXUI_SCREEN_SCREEN_HPP
 #define FTXUI_SCREEN_SCREEN_HPP
 
+#include <cstdint>  // for uint8_t
 #include <memory>
-#include <string>  // for string, allocator, basic_string
+#include <string>  // for string, basic_string, allocator
 #include <vector>  // for vector
 
 #include "ftxui/screen/box.hpp"       // for Box
@@ -20,6 +21,10 @@ struct Pixel {
   // like: a⃦, this can potentially contains multiple codepoitns.
   std::string character = " ";
 
+  // The hyperlink associated with the pixel.
+  // 0 is the default value, meaning no hyperlink.
+  uint8_t hyperlink = 0;
+
   // Colors:
   Color background_color = Color::Default;
   Color foreground_color = Color::Default;
@@ -99,6 +104,11 @@ class Screen {
   Cursor cursor() const { return cursor_; }
   void SetCursor(Cursor cursor) { cursor_ = cursor; }
 
+  // Store an hyperlink in the screen. Return the id of the hyperlink. The id is
+  // used to identify the hyperlink when the user click on it.
+  uint8_t RegisterHyperlink(std::string link);
+  const std::string& Hyperlink(uint8_t id) const;
+
   Box stencil;
 
  protected:
@@ -106,6 +116,7 @@ class Screen {
   int dimy_;
   std::vector<std::vector<Pixel>> pixels_;
   Cursor cursor_;
+  std::vector<std::string> hyperlinks_ = {""};
 };
 
 }  // namespace ftxui
diff --git a/iwyu.imp b/iwyu.imp
index 83d8d4226e82ba61d8eefb97cdb848a3a0538216..4a146409f538703ec8755549937dff6d1c86f6d2 100644
--- a/iwyu.imp
+++ b/iwyu.imp
@@ -14,6 +14,32 @@
   { include: ["<gtest/gtest-printers.h>", "private", "<gtest/gtest.h>", "public" ] },
   { include: ["<gtest/gtest-test-part.h>", "private", "<gtest/gtest.h>", "public" ] },
   { include: ["<gtest/gtest-typed-test.h>", "private", "<gtest/gtest.h>", "public" ] },
+  { include: ["<assert.h>", "private", "<cassert>", "public" ] },
+  { include: ["<complex.h>", "private", "<ccomplex>", "public" ] },
+  { include: ["<ctype.h>", "private", "<cctype>", "public" ] },
+  { include: ["<errno.h>", "private", "<cerrno>", "public" ] },
+  { include: ["<fenv.h>", "private", "<cfenv>", "public" ] },
+  { include: ["<float.h>", "private", "<cfloat>", "public" ] },
+  { include: ["<inttypes.h>", "private", "<cinttypes>", "public" ] },
+  { include: ["<iso646.h>", "private", "<ciso646>", "public" ] },
+  { include: ["<limits.h>", "private", "<climits>", "public" ] },
+  { include: ["<locale.h>", "private", "<clocale>", "public" ] },
+  { include: ["<math.h>", "private", "<cmath>", "public" ] },
+  { include: ["<setjmp.h>", "private", "<csetjmp>", "public" ] },
+  { include: ["<signal.h>", "private", "<csignal>", "public" ] },
+  { include: ["<stdalign.h>", "private", "<cstdalign>", "public" ] },
+  { include: ["<stdarg.h>", "private", "<cstdarg>", "public" ] },
+  { include: ["<stdbool.h>", "private", "<cstdbool>", "public" ] },
+  { include: ["<stddef.h>", "private", "<cstddef>", "public" ] },
+  { include: ["<stdint.h>", "private", "<cstdint>", "public" ] },
+  { include: ["<stdio.h>", "private", "<cstdio>", "public" ] },
+  { include: ["<stdlib.h>", "private", "<cstdlib>", "public" ] },
+  { include: ["<string.h>", "private", "<cstring>", "public" ] },
+  { include: ["<tgmath.h>", "private", "<ctgmath>", "public" ] },
+  { include: ["<time.h>", "private", "<ctime>", "public" ] },
+  { include: ["<uchar.h>", "private", "<cuchar>", "public" ] },
+  { include: ["<wchar.h>", "private", "<cwchar>", "public" ] },
+  { include: ["<wctype.h>", "private", "<cwctype>", "public" ] },
   { symbol: ["ftxui", "private", "", "public" ] },
   { symbol: ["char_traits", "private", "<string>", "public" ] },
   { symbol: ["ECHO", "private", "<termios.h>", "public" ] },
diff --git a/src/ftxui/component/input.cpp b/src/ftxui/component/input.cpp
index a854614eeb287004ea283e12553a515907b60426..c19b508d2903a0998761cd2dc1263580d00e9015 100644
--- a/src/ftxui/component/input.cpp
+++ b/src/ftxui/component/input.cpp
@@ -1,6 +1,6 @@
-#include <stdint.h>    // for uint32_t
 #include <algorithm>   // for max, min
 #include <cstddef>     // for size_t
+#include <cstdint>     // for uint32_t
 #include <functional>  // for function
 #include <memory>   // for allocator, shared_ptr, allocator_traits<>::value_type
 #include <sstream>  // for basic_istream, stringstream
diff --git a/src/ftxui/dom/hyperlink.cpp b/src/ftxui/dom/hyperlink.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6ce8a7ad8afbbab4f0b9ec58b6804975f4c7a2f4
--- /dev/null
+++ b/src/ftxui/dom/hyperlink.cpp
@@ -0,0 +1,72 @@
+#include <cstdint>  // for uint8_t
+#include <memory>   // for make_shared
+#include <string>   // for string
+#include <utility>  // for move
+
+#include "ftxui/dom/elements.hpp"        // for Element, Decorator, hyperlink
+#include "ftxui/dom/node_decorator.hpp"  // for NodeDecorator
+#include "ftxui/screen/box.hpp"          // for Box
+#include "ftxui/screen/screen.hpp"       // for Screen, Pixel
+
+namespace ftxui {
+
+class Hyperlink : public NodeDecorator {
+ public:
+  Hyperlink(Element child, std::string link)
+      : NodeDecorator(std::move(child)), link_(link) {}
+
+  void Render(Screen& screen) override {
+    uint8_t hyperlink_id = screen.RegisterHyperlink(link_);
+    for (int y = box_.y_min; y <= box_.y_max; ++y) {
+      for (int x = box_.x_min; x <= box_.x_max; ++x) {
+        screen.PixelAt(x, y).hyperlink = hyperlink_id;
+      }
+    }
+    NodeDecorator::Render(screen);
+  }
+
+  std::string link_;
+};
+
+/// @brief Make the rendered area clickable using a web browser.
+///        The link will be opened when the user click on it.
+///        This is supported only on a limited set of terminal emulator.
+///        List: https://github.com/Alhadis/OSC8-Adoption/
+/// @param link The link
+/// @param child The input element.
+/// @return The output element with the link.
+/// @ingroup dom
+///
+/// ### Example
+///
+/// ```cpp
+/// Element document =
+///   hyperlink("https://github.com/ArthurSonzogni/FTXUI", "link");
+/// ```
+Element hyperlink(std::string link, Element child) {
+  return std::make_shared<Hyperlink>(std::move(child), link);
+}
+
+/// @brief Decorate using an hyperlink.
+///        The link will be opened when the user click on it.
+///        This is supported only on a limited set of terminal emulator.
+///        List: https://github.com/Alhadis/OSC8-Adoption/
+/// @param link The link to redirect the users to.
+/// @return The Decorator applying the hyperlink.
+/// @ingroup dom
+///
+/// ### Example
+///
+/// ```cpp
+/// Element document =
+///   text("red") | hyperlink("https://github.com/Arthursonzogni/FTXUI");
+/// ```
+Decorator hyperlink(std::string link) {
+  return [link](Element child) { return hyperlink(link, std::move(child)); };
+}
+
+}  // namespace ftxui
+
+// Copyright 2023 Arthur Sonzogni. All rights reserved.
+// Use of this source code is governed by the MIT license that can be found in
+// the LICENSE file.
diff --git a/src/ftxui/dom/hyperlink_test.cpp b/src/ftxui/dom/hyperlink_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5579831421655fd578fcbd0feb7cef2f7fa5f2da
--- /dev/null
+++ b/src/ftxui/dom/hyperlink_test.cpp
@@ -0,0 +1,43 @@
+#include <gtest/gtest.h>  // for Test, EXPECT_EQ, Message, TestPartResult, TestInfo (ptr only), TEST
+#include <string>  // for allocator, string
+
+#include "ftxui/dom/elements.hpp"  // for text, hyperlink, operator|, Element, hbox
+#include "ftxui/dom/node.hpp"      // for Render
+#include "ftxui/screen/screen.hpp"  // for Screen, Pixel
+
+namespace ftxui {
+
+TEST(HyperlinkTest, Basic) {
+  auto element = hbox({
+      text("text 1") | hyperlink("https://a.com"),
+      text("text 2") | hyperlink("https://b.com"),
+      text("text 3"),
+      text("text 4") | hyperlink("https://c.com"),
+  });
+
+  Screen screen(6 * 4, 1);
+  Render(screen, element);
+
+  EXPECT_EQ(screen.PixelAt(0, 0).hyperlink, 1u);
+  EXPECT_EQ(screen.PixelAt(5, 0).hyperlink, 1u);
+  EXPECT_EQ(screen.PixelAt(6, 0).hyperlink, 2u);
+  EXPECT_EQ(screen.PixelAt(11, 0).hyperlink, 2u);
+
+  std::string output = screen.ToString();
+  EXPECT_EQ(output,
+            "\x1B]8;;https://a.com\x1B\\"
+            "text 1"
+            "\x1B]8;;https://b.com\x1B\\"
+            "text 2"
+            "\x1B]8;;\x1B\\"
+            "text 3"
+            "\x1B]8;;https://c.com\x1B\\"
+            "text 4"
+            "\x1B]8;;\x1B\\");
+}
+
+}  // namespace ftxui
+
+// Copyright 2023 Arthur Sonzogni. All rights reserved.
+// Use of this source code is governed by the MIT license that can be found in
+// the LICENSE file.
diff --git a/src/ftxui/screen/screen.cpp b/src/ftxui/screen/screen.cpp
index 04cc758411b36452fae4bdb42edc3f0513308f92..0f2e3772e00bc0742e8f92ce5ea7418be2f3e1cb 100644
--- a/src/ftxui/screen/screen.cpp
+++ b/src/ftxui/screen/screen.cpp
@@ -1,7 +1,7 @@
-#include <cstdint>  // for uint8_t
+#include <cstdint>  // for size_t
 #include <iostream>  // for operator<<, stringstream, basic_ostream, flush, cout, ostream
 #include <map>      // for _Rb_tree_const_iterator, map, operator!=, operator==
-#include <memory>   // for allocator
+#include <memory>   // for allocator, allocator_traits<>::value_type
 #include <sstream>  // IWYU pragma: keep
 #include <utility>  // for pair
 
@@ -50,11 +50,13 @@ void WindowsEmulateVT100Terminal() {
 #endif
 
 // NOLINTNEXTLINE(readability-function-cognitive-complexity)
-void UpdatePixelStyle(std::stringstream& ss,
+void UpdatePixelStyle(const Screen* screen,
+                      std::stringstream& ss,
                       Pixel& previous,
                       const Pixel& next) {
-  if (next == previous) {
-    return;
+  // See https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
+  if (next.hyperlink != previous.hyperlink) {
+    ss << "\x1B]8;;" << screen->Hyperlink(next.hyperlink) << "\x1B\\";
   }
 
   if ((!next.bold && previous.bold) ||  //
@@ -435,20 +437,20 @@ std::string Screen::ToString() {
 
   for (int y = 0; y < dimy_; ++y) {
     if (y != 0) {
-      UpdatePixelStyle(ss, previous_pixel, final_pixel);
+      UpdatePixelStyle(this, ss, previous_pixel, final_pixel);
       ss << "\r\n";
     }
     bool previous_fullwidth = false;
     for (const auto& pixel : pixels_[y]) {
       if (!previous_fullwidth) {
-        UpdatePixelStyle(ss, previous_pixel, pixel);
+        UpdatePixelStyle(this, ss, previous_pixel, pixel);
         ss << pixel.character;
       }
       previous_fullwidth = (string_width(pixel.character) == 2);
     }
   }
 
-  UpdatePixelStyle(ss, previous_pixel, final_pixel);
+  UpdatePixelStyle(this, ss, previous_pixel, final_pixel);
 
   return ss.str();
 }
@@ -517,6 +519,10 @@ void Screen::Clear() {
   }
   cursor_.x = dimx_ - 1;
   cursor_.y = dimy_ - 1;
+
+  hyperlinks_ = {
+      "",
+  };
 }
 
 // clang-format off
@@ -545,9 +551,28 @@ void Screen::ApplyShader() {
     }
   }
 }
-
 // clang-format on
 
+uint8_t Screen::RegisterHyperlink(std::string link) {
+  for (size_t i = 0; i < hyperlinks_.size(); ++i) {
+    if (hyperlinks_[i] == link) {
+      return i;
+    }
+  }
+  if (hyperlinks_.size() == 255) {
+    return 0;
+  }
+  hyperlinks_.push_back(link);
+  return hyperlinks_.size() - 1;
+}
+
+const std::string& Screen::Hyperlink(uint8_t id) const {
+  if (id >= hyperlinks_.size()) {
+    return hyperlinks_[0];
+  }
+  return hyperlinks_[id];
+}
+
 }  // namespace ftxui
 
 // Copyright 2020 Arthur Sonzogni. All rights reserved.