diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/QueueController.php b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/QueueController.php
index 6dd96e729b764e9211526c6129c00df6458dd14d..991647c89c72d4b6c389aff76c3729b2039c50ba 100644
--- a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/QueueController.php
+++ b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/QueueController.php
@@ -90,13 +90,10 @@ class QueueController extends ActionController
 
     public function finishAction(): ResponseInterface
     {
-        $typoScriptFrontendController = $GLOBALS['TSFE'];
-        $typoScriptFrontendController->setContentType('application/json');
-
         $value = $this->queueService->getValues();
         $this->view->assign('value', $value);
         $body = new Stream('php://temp', 'rw');
         $body->write($this->view->render());
-        return new Response($body);
+        return (new Response($body))->withHeader('Content-Type', 'application/json; charset=utf-8');
     }
 }
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_irre_foreignfield/Classes/Controller/QueueController.php b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_irre_foreignfield/Classes/Controller/QueueController.php
index c221eb3654ae5599dbfea8241f0e4e94fbbf3de1..8b518e6c6f14fbd558aa3391aadb9e849397f146 100644
--- a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_irre_foreignfield/Classes/Controller/QueueController.php
+++ b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_irre_foreignfield/Classes/Controller/QueueController.php
@@ -90,13 +90,10 @@ class QueueController extends ActionController
 
     public function finishAction(): ResponseInterface
     {
-        $typoScriptFrontendController = $GLOBALS['TSFE'];
-        $typoScriptFrontendController->setContentType('application/json');
-
         $value = $this->queueService->getValues();
         $this->view->assign('value', $value);
         $body = new Stream('php://temp', 'rw');
         $body->write($this->view->render());
-        return new Response($body);
+        return (new Response($body))->withHeader('Content-Type', 'application/json; charset=utf-8');
     }
 }
diff --git a/typo3/sysext/extbase/Classes/Core/Bootstrap.php b/typo3/sysext/extbase/Classes/Core/Bootstrap.php
index a65100315c8ad885b1cfa9bd8340ed5c31da8e11..2b9b79b8bcbe6d2986e966f8746eb27c39f5b6d8 100644
--- a/typo3/sysext/extbase/Classes/Core/Bootstrap.php
+++ b/typo3/sysext/extbase/Classes/Core/Bootstrap.php
@@ -176,24 +176,14 @@ class Bootstrap
             $this->clearCacheOnError();
         }
 
-        // In case TSFE is available and this is a json response, we have
-        // to take the TypoScript settings regarding charset into account.
-        // @todo Since HTML5 only utf-8 is a valid charset, this settings should be deprecated
+        // In case TSFE is available and this is a json response, we have to let TSFE know we have a specific Content-Type
         if (($typoScriptFrontendController = ($GLOBALS['TSFE'] ?? null)) instanceof TypoScriptFrontendController
-            && strpos($response->getHeaderLine('Content-Type'), 'application/json') === 0
+            && $response->hasHeader('Content-Type')
         ) {
-            // Unset the already defined Content-Type
+            [$contentType] = explode(';', $response->getHeaderLine('Content-Type'));
+            // Do not send the header directly (see below)
             $response = $response->withoutHeader('Content-Type');
-            if (empty($typoScriptFrontendController->config['config']['disableCharsetHeader'])) {
-                // If the charset header is *not* disabled in configuration,
-                // TypoScriptFrontendController will send the header later with the Content-Type which we set here.
-                $typoScriptFrontendController->setContentType('application/json');
-            } else {
-                // Although the charset header is disabled in configuration, we *must* send a Content-Type header here.
-                // Content-Type headers optionally carry charset information at the same time.
-                // Since we have the information about the charset, there is no reason to not include the charset information although disabled in TypoScript.
-                $response = $response->withHeader('Content-Type', 'application/json; charset=' . trim($typoScriptFrontendController->metaCharset));
-            }
+            $typoScriptFrontendController->setContentType($contentType);
         }
 
         if (headers_sent() === false) {
diff --git a/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php b/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php
index b2672237a7aa4a2f176fd78e8a8a157a733c30de..3e46d116c810cbeae1a572aefa81adf00d3d6ec9 100644
--- a/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php
+++ b/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php
@@ -663,7 +663,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
 
     /**
      * @param string $contentType
-     * @internal Should only be used by TYPO3 core for now
+     * @internal Must only be used by TYPO3 core
      */
     public function setContentType($contentType)
     {
@@ -1676,6 +1676,8 @@ class TypoScriptFrontendController implements LoggerAwareInterface
         $this->config = $cachedData['cache_data'];
         // Getting the content
         $this->content = $cachedData['content'];
+        // Getting the content type
+        $this->contentType = $cachedData['contentType'] ?? $this->contentType;
         // Setting flag, so we know, that some cached content has been loaded
         $this->cacheContentFlag = true;
         $this->cacheExpires = $cachedData['expires'];
@@ -2374,6 +2376,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
             'identifier' => $this->newHash,
             'page_id' => $this->id,
             'content' => $content,
+            'contentType' => $this->contentType,
             'cache_data' => $data,
             'expires' => $expirationTstamp,
             'tstamp' => $GLOBALS['EXEC_TIME'],