diff --git a/CMakeLists.txt b/CMakeLists.txt
index e3ab47ea19..6af81a2fb6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -987,6 +987,8 @@ set(LIBNETDATA_FILES
         src/libnetdata/memory/alignment.h
         src/libnetdata/os/get_system_pagesize.c
         src/libnetdata/os/get_system_pagesize.h
+        src/libnetdata/os/hostname.c
+        src/libnetdata/os/hostname.h
 )
 
 set(LIBH2O_FILES
diff --git a/packaging/cmake/config.cmake.h.in b/packaging/cmake/config.cmake.h.in
index 292474da8c..32bad0b85a 100644
--- a/packaging/cmake/config.cmake.h.in
+++ b/packaging/cmake/config.cmake.h.in
@@ -68,6 +68,7 @@
 #cmakedefine HAVE_SETENV
 #cmakedefine HAVE_DLSYM
 #cmakedefine HAVE_LIBCURL
+#cmakedefine HAVE_LIBICONV
 
 #cmakedefine HAVE_ARC4RANDOM_BUF
 #cmakedefine HAVE_ARC4RANDOM_UNIFORM
diff --git a/src/daemon/config/netdata-conf-global.c b/src/daemon/config/netdata-conf-global.c
index cf0d609439..7c41586e87 100644
--- a/src/daemon/config/netdata-conf-global.c
+++ b/src/daemon/config/netdata-conf-global.c
@@ -40,22 +40,6 @@ skip:
     return processors;
 }
 
-static int get_hostname(char *buf, size_t buf_size) {
-    if (netdata_configured_host_prefix && *netdata_configured_host_prefix) {
-        char filename[FILENAME_MAX + 1];
-        snprintfz(filename, FILENAME_MAX, "%s/etc/hostname", netdata_configured_host_prefix);
-
-        if (!read_txt_file(filename, buf, buf_size)) {
-            trim(buf);
-            return 0;
-        }
-    }
-
-    int rc = gethostname(buf, buf_size);
-    buf[buf_size - 1] = '\0';
-    return rc;
-}
-
 void netdata_conf_glibc_malloc_initialize(size_t wanted_arenas, size_t trim_threshold __maybe_unused) {
     wanted_arenas = config_get_number(CONFIG_SECTION_GLOBAL, "glibc malloc arena max for plugins", wanted_arenas);
     if(wanted_arenas < 1 || wanted_arenas > os_get_system_cpus_cached(true)) {
@@ -119,8 +103,8 @@ void netdata_conf_section_global(void) {
     netdata_configured_host_prefix = config_get(CONFIG_SECTION_GLOBAL, "host access prefix", "");
     (void) verify_netdata_host_prefix(true);
 
-    char buf[HOSTNAME_MAX + 1];
-    if (get_hostname(buf, sizeof(buf)))
+    char buf[HOST_NAME_MAX * 4 + 1];
+    if (!os_hostname(buf, sizeof(buf), netdata_configured_host_prefix))
         netdata_log_error("Cannot get machine hostname.");
 
     netdata_configured_hostname = config_get(CONFIG_SECTION_GLOBAL, "hostname", buf);
diff --git a/src/daemon/pulse/pulse-daemon-memory-system.c b/src/daemon/pulse/pulse-daemon-memory-system.c
index 8ce7e8766d..ed41b04b62 100644
--- a/src/daemon/pulse/pulse-daemon-memory-system.c
+++ b/src/daemon/pulse/pulse-daemon-memory-system.c
@@ -107,7 +107,7 @@ cleanup:
 }
 #endif // HAVE_C_MALLOC_INFO
 
-void pulse_daemon_memory_system_do(bool extended) {
+void pulse_daemon_memory_system_do(bool extended __maybe_unused) {
 
 #ifdef HAVE_C_MALLOC_INFO
     size_t glibc_arenas, glibc_allocated_arenas, glibc_unused_fast, glibc_unused_rest, glibc_allocated_mmap;
diff --git a/src/database/rrdlabels.c b/src/database/rrdlabels.c
index 24c9db7343..37072d0068 100644
--- a/src/database/rrdlabels.c
+++ b/src/database/rrdlabels.c
@@ -1577,6 +1577,10 @@ int rrdlabels_unittest_sanitization() {
     const unsigned char invalid5[] = "app.clewd修改\xe7\x89_fd_open_limits";
     errors += rrdlabels_unittest_sanitize_value((const char *)invalid5, "app.clewd修改e789_fd_open_limits");
 
+    // invalid UTF8 No 6
+    const unsigned char invalid6[] = "\260\327\312\300\322\242";
+    errors += rrdlabels_unittest_sanitize_value((const char *)invalid6, "d7cac0Ң");
+
     return errors;
 }
 
diff --git a/src/libnetdata/common.h b/src/libnetdata/common.h
index 6124b8d835..13f877c809 100644
--- a/src/libnetdata/common.h
+++ b/src/libnetdata/common.h
@@ -400,6 +400,12 @@ typedef uint32_t uid_t;
 
 // --------------------------------------------------------------------------------------------------------------------
 
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 256
+#endif
+
+// --------------------------------------------------------------------------------------------------------------------
+
 #if defined(OS_WINDOWS)
 #include <windows.h>
 #include <wctype.h>
diff --git a/src/libnetdata/os/hostname.c b/src/libnetdata/os/hostname.c
new file mode 100644
index 0000000000..62ec4d0752
--- /dev/null
+++ b/src/libnetdata/os/hostname.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "libnetdata/libnetdata.h"
+
+#if defined(OS_WINDOWS)
+bool os_hostname(char *dst, size_t dst_size, const char *filesystem_root __maybe_unused) {
+    WCHAR wbuf[HOST_NAME_MAX * 4 + 1];
+    char buf[HOST_NAME_MAX * 4 + 1];
+    DWORD size = _countof(wbuf);
+    bool success = false;
+
+    // First try DNS hostname
+    if (GetComputerNameExW(ComputerNameDnsHostname, wbuf, &size)) {
+        success = true;
+    }
+    // Then try NetBIOS name
+    else {
+        size = _countof(wbuf);
+        if (GetComputerNameW(wbuf, &size)) {
+            success = true;
+        }
+    }
+
+    if (success) {
+        // Convert UTF-16 to UTF-8
+        int utf8_size = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, NULL, 0, NULL, NULL);
+        if (utf8_size > 0 && utf8_size <= (int)sizeof(buf)) {
+            WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, utf8_size, NULL, NULL);
+        }
+        else {
+            success = false;
+        }
+    }
+
+    if (!success) {
+        // Try getting the machine GUID first
+        HKEY hKey;
+        if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography", 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
+            WCHAR guidW[64];
+            DWORD guidSize = sizeof(guidW);
+            DWORD type = REG_SZ;
+
+            if (RegQueryValueExW(hKey, L"MachineGuid", NULL, &type, (LPBYTE)guidW, &guidSize) == ERROR_SUCCESS) {
+                // Convert GUID to UTF-8
+                if (WideCharToMultiByte(CP_UTF8, 0, guidW, -1, buf, sizeof(buf), NULL, NULL) > 0) {
+                    success = true;
+                }
+            }
+            RegCloseKey(hKey);
+        }
+
+        if (!success) {
+            // If machine GUID fails, try getting volume serial number of C: drive
+            WCHAR rootPath[] = L"C:\\";
+            DWORD serialNumber;
+            if (GetVolumeInformationW(rootPath, NULL, 0, &serialNumber, NULL, NULL, NULL, 0)) {
+                snprintf(buf, sizeof(buf), "host%08lx", (long unsigned)serialNumber);
+                success = true;
+            }
+            else {
+                // Last resort: use process ID
+                snprintf(buf, sizeof(buf), "host%lu", (long unsigned)GetCurrentProcessId());
+            }
+        }
+    }
+
+    char *hostname = trim(buf);
+    rrdlabels_sanitize_value(dst, hostname, dst_size);
+    return *dst != '\0';
+}
+#else // !OS_WINDOWS
+
+#ifdef HAVE_LIBICONV
+#include <iconv.h>
+
+static const char *get_current_locale(void) {
+    const char *locale = getenv("LC_ALL");  // LC_ALL overrides all other locale settings
+
+    if (!locale || !*locale) {
+        locale = getenv("LC_CTYPE");  // Check LC_CTYPE for character encoding
+
+        if (!locale || !*locale)
+            locale = getenv("LANG");  // Fallback to LANG
+    }
+
+    return locale;
+}
+
+static const char *get_encoding_from_locale(const char *locale) {
+    if(!locale || !*locale)
+        return NULL;
+
+    const char *dot = strchr(locale, '.');
+    if (dot)
+        return dot + 1;
+
+    return locale;
+}
+
+// Function to convert from a source encoding to UTF-8
+static bool iconv_convert_to_utf8(const char *input, const char *src_encoding, char *output, size_t output_size) {
+    iconv_t cd = iconv_open("UTF-8", src_encoding);
+    if (cd == (iconv_t)-1) {
+        int i = errno;
+        return false;
+    }
+
+    char *input_ptr = (char *)input;    // iconv() may modify this pointer
+    char *output_ptr = output;          // iconv() modifies this pointer
+    size_t input_len = strlen(input);
+    size_t output_len = output_size;
+
+    // Perform the conversion
+    if (iconv(cd, &input_ptr, &input_len, &output_ptr, &output_len) == (size_t)-1) {
+        iconv_close(cd);
+        return false;
+    }
+
+    // Null-terminate the output string
+    *output_ptr = '\0';
+
+    iconv_close(cd);
+    return true;
+}
+#endif
+
+bool os_hostname(char *dst, size_t dst_size, const char *filesystem_root) {
+    *dst = '\0';
+
+    char buf[HOST_NAME_MAX * 4 + 1];
+    *buf = '\0';
+
+    if (filesystem_root && *filesystem_root) {
+        char filename[FILENAME_MAX + 1];
+        snprintfz(filename, FILENAME_MAX, "%s/etc/hostname", netdata_configured_host_prefix);
+
+        if (read_txt_file(filename, buf, sizeof(buf)))
+            *buf = '\0';
+    }
+
+    if(!*buf && gethostname(buf, sizeof(buf)) != 0)
+        snprintf(buf, sizeof(buf), "host%ld", gethostid());
+
+    char *original_hostname = trim(buf);
+
+#ifdef HAVE_LIBICONV
+    const char *locale = get_current_locale();
+    if (locale && *locale) {
+        char utf8_output[HOST_NAME_MAX * 4 + 1] = "";
+        if(iconv_convert_to_utf8(original_hostname, get_encoding_from_locale(locale), utf8_output, sizeof(utf8_output))) {
+            rrdlabels_sanitize_value(dst, trim(utf8_output), dst_size);
+            return *dst != '\0';
+        }
+    }
+#endif
+
+    rrdlabels_sanitize_value(dst, original_hostname, dst_size);
+    return *dst != '\0';
+}
+
+#endif // !OS_WINDOWS
diff --git a/src/libnetdata/os/hostname.h b/src/libnetdata/os/hostname.h
new file mode 100644
index 0000000000..77c8b2391b
--- /dev/null
+++ b/src/libnetdata/os/hostname.h
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_HOSTNAME_H
+#define NETDATA_HOSTNAME_H
+
+#include "libnetdata/libnetdata.h"
+
+/**
+ * Get system hostname in UTF-8 encoding
+ *
+ * @param dst Buffer to store the hostname
+ * @param dst_size Size of the destination buffer
+ * @param filesystem_root Optional root directory (for Unix-like systems, when running in a container)
+ * @return true on success, false on failure
+ *
+ * The function guarantees to return a UTF-8 encoded hostname.
+ * On Windows, filesystem_root is ignored.
+ */
+ bool os_hostname(char *dst, size_t dst_size, const char *filesystem_root);
+
+#endif //NETDATA_HOSTNAME_H
diff --git a/src/libnetdata/os/os.h b/src/libnetdata/os/os.h
index 4168e72333..ee01b18a21 100644
--- a/src/libnetdata/os/os.h
+++ b/src/libnetdata/os/os.h
@@ -23,6 +23,7 @@
 #include "sleep.h"
 #include "uuid_generate.h"
 #include "setenv.h"
+#include "hostname.h"
 #include "os-freebsd-wrappers.h"
 #include "os-macos-wrappers.h"
 #include "os-windows-wrappers.h"
diff --git a/src/web/api/formatters/rrd2json.h b/src/web/api/formatters/rrd2json.h
index cf3492ff28..a5f633228f 100644
--- a/src/web/api/formatters/rrd2json.h
+++ b/src/web/api/formatters/rrd2json.h
@@ -18,8 +18,6 @@
 
 #include "web/server/web_client.h"
 
-#define HOSTNAME_MAX 1024
-
 void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb);
 
 int data_query_execute(ONEWAYALLOC *owa, BUFFER *wb, struct query_target *qt, time_t *latest_timestamp);