diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index aa9d0a2f2f..137457c722 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -902,7 +902,12 @@ bool setupEssentials(const QCommandLineParser& parser, bool runningMarkerExisted
     DependencyManager::set<CompositorHelper>();
     DependencyManager::set<OffscreenQmlSurfaceCache>();
     DependencyManager::set<EntityScriptClient>();
+
     DependencyManager::set<EntityScriptServerLogClient>();
+    auto scriptEngines = DependencyManager::get<ScriptEngines>();
+    auto entityScriptServerLog = DependencyManager::get<EntityScriptServerLogClient>();
+    QObject::connect(scriptEngines.data(), &ScriptEngines::requestingEntityScriptServerLog, entityScriptServerLog.data(), &EntityScriptServerLogClient::requestMessagesForScriptEngines);
+
     DependencyManager::set<GooglePolyScriptingInterface>();
     DependencyManager::set<OctreeStatsProvider>(nullptr, qApp->getOcteeSceneStats());
     DependencyManager::set<AvatarBookmarks>();
diff --git a/libraries/entities/src/EntityScriptServerLogClient.cpp b/libraries/entities/src/EntityScriptServerLogClient.cpp
index 5c21f01776..7329cf1fdd 100644
--- a/libraries/entities/src/EntityScriptServerLogClient.cpp
+++ b/libraries/entities/src/EntityScriptServerLogClient.cpp
@@ -39,9 +39,9 @@ void EntityScriptServerLogClient::disconnectNotify(const QMetaMethod& signal) {
 
 void EntityScriptServerLogClient::connectionsChanged() {
     auto numReceivers = receivers(SIGNAL(receivedNewLogLines(QString)));
-    if (!_subscribed && numReceivers > 0) {
+    if (!_subscribed && (numReceivers > 0 || _areMessagesRequestedByScripts)) {
         enableToEntityServerScriptLog(DependencyManager::get<NodeList>()->getThisNodeCanRez());
-    } else if (_subscribed && numReceivers == 0) {
+    } else if (_subscribed && (numReceivers == 0 && !_areMessagesRequestedByScripts)) {
         enableToEntityServerScriptLog(false);
     }
 }
@@ -140,3 +140,8 @@ void EntityScriptServerLogClient::canRezChanged(bool canRez) {
         enableToEntityServerScriptLog(canRez);
     }
 }
+
+void EntityScriptServerLogClient::requestMessagesForScriptEngines(bool areMessagesRequested) {
+    _areMessagesRequestedByScripts = areMessagesRequested;
+    connectionsChanged();
+}
diff --git a/libraries/entities/src/EntityScriptServerLogClient.h b/libraries/entities/src/EntityScriptServerLogClient.h
index 9eee5daed8..e388de917a 100644
--- a/libraries/entities/src/EntityScriptServerLogClient.h
+++ b/libraries/entities/src/EntityScriptServerLogClient.h
@@ -33,6 +33,12 @@ class EntityScriptServerLogClient : public QObject, public Dependency {
 public:
     EntityScriptServerLogClient();
 
+    /**
+     * @brief This is called by ScriptEngines when scripts need access to entity server script messages and when access
+     * is not needed anymore.
+     */
+    void requestMessagesForScriptEngines(bool areMessagesRequested);
+
 signals:
 
     /*@jsdoc
@@ -66,7 +72,10 @@ private slots:
     void connectionsChanged();
 
 private:
+    std::atomic<bool> _areMessagesRequestedByScripts {false};
     bool _subscribed { false };
+
+    friend class ScriptEngines;
 };
 
 #endif // hifi_EntityScriptServerLogClient_h
diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp
index b47255ed24..52d3b2753b 100644
--- a/libraries/script-engine/src/ScriptEngines.cpp
+++ b/libraries/script-engine/src/ScriptEngines.cpp
@@ -158,8 +158,69 @@ void ScriptEngines::removeScriptEngine(ScriptManagerPointer manager) {
         QMutexLocker locker(&_allScriptsMutex);
         _allKnownScriptManagers.remove(manager);
     }
+    std::lock_guard<std::mutex> lock(_subscriptionsToEntityScriptMessagesMutex);
+    _managersSubscribedToEntityScriptMessages.remove(manager.get());
+    _entitiesSubscribedToEntityScriptMessages.remove(manager.get());
 }
 
+void ScriptEngines::requestServerEntityScriptMessages(ScriptManager *manager) {
+    std::lock_guard<std::mutex> lock(_subscriptionsToEntityScriptMessagesMutex);
+    if (!_managersSubscribedToEntityScriptMessages.contains(manager)) {
+        _managersSubscribedToEntityScriptMessages.insert(manager);
+        // Emit a signal to inform EntityScriptServerLogClient about subscription request
+        emit requestingEntityScriptServerLog(true);
+        qDebug() << "ScriptEngines::requestServerEntityScriptMessages";
+    }
+}
+
+void ScriptEngines::requestServerEntityScriptMessages(ScriptManager *manager, const QUuid& entityID) {
+    std::lock_guard<std::mutex> lock(_subscriptionsToEntityScriptMessagesMutex);
+    if (!_entitiesSubscribedToEntityScriptMessages.contains(manager)) {
+        _entitiesSubscribedToEntityScriptMessages.insert(manager,QSet<QUuid>());
+    }
+    if (!_entitiesSubscribedToEntityScriptMessages[manager].contains(entityID)) {
+        _entitiesSubscribedToEntityScriptMessages[manager].insert(entityID);
+        // Emit a signal to inform EntityScriptServerLogClient about subscription request
+        emit requestingEntityScriptServerLog(true);
+        qDebug() << "ScriptEngines::requestServerEntityScriptMessages uuid";
+    }
+}
+
+void ScriptEngines::removeServerEntityScriptMessagesRequest(ScriptManager *manager) {
+    std::lock_guard<std::mutex> lock(_subscriptionsToEntityScriptMessagesMutex);
+    if (_managersSubscribedToEntityScriptMessages.contains(manager)) {
+        _managersSubscribedToEntityScriptMessages.remove(manager);
+    }
+    if (_entitiesSubscribedToEntityScriptMessages.isEmpty()
+        && _managersSubscribedToEntityScriptMessages.isEmpty()) {
+        // No managers requiring entity script server messages remain, so we inform EntityScriptServerLogClient about this
+        // Emit a signal to inform EntityScriptServerLogClient about subscription request
+        emit requestingEntityScriptServerLog(false);
+        qDebug() << "ScriptEngines::removeServerEntityScriptMessagesRequest";
+    }
+}
+
+void ScriptEngines::removeServerEntityScriptMessagesRequest(ScriptManager *manager, const QUuid& entityID) {
+    std::lock_guard<std::mutex> lock(_subscriptionsToEntityScriptMessagesMutex);
+    if (!_entitiesSubscribedToEntityScriptMessages.contains(manager)) {
+        return;
+    }
+    if (_entitiesSubscribedToEntityScriptMessages[manager].contains(entityID)) {
+        _entitiesSubscribedToEntityScriptMessages[manager].remove(entityID);
+    }
+    if (_entitiesSubscribedToEntityScriptMessages[manager].isEmpty()) {
+        _entitiesSubscribedToEntityScriptMessages.remove(manager);
+    }
+    if (_entitiesSubscribedToEntityScriptMessages.isEmpty()
+        && _managersSubscribedToEntityScriptMessages.isEmpty()) {
+        // No managers requiring entity script server messages remain, so we inform EntityScriptServerLogClient about this
+        // Emit a signal to inform EntityScriptServerLogClient about subscription request
+        emit requestingEntityScriptServerLog(false);
+        qDebug() << "ScriptEngines::removeServerEntityScriptMessagesRequest uuid";
+    }
+}
+
+
 void ScriptEngines::shutdownScripting() {
     _isStopped = true;
     QMutexLocker locker(&_allScriptsMutex);
diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h
index 1a4e3c4389..bafaa1322c 100644
--- a/libraries/script-engine/src/ScriptEngines.h
+++ b/libraries/script-engine/src/ScriptEngines.h
@@ -186,6 +186,13 @@ public:
 
     void removeScriptEngine(ScriptManagerPointer);
 
+    // Called by ScriptManagerScriptingInterface
+    void requestServerEntityScriptMessages(ScriptManager *manager);
+    void requestServerEntityScriptMessages(ScriptManager *manager, const QUuid& entityID);
+
+    void removeServerEntityScriptMessagesRequest(ScriptManager *manager);
+    void removeServerEntityScriptMessagesRequest(ScriptManager *manager, const QUuid& entityID);
+
     ScriptGatekeeper scriptGatekeeper;
 
 signals:
@@ -323,6 +330,12 @@ signals:
      */
     void clearDebugWindow();
 
+    /**
+     * @brief Fires when script engines need entity server script messages (areMessagesRequested == true)
+     * and when messages are not needed anymore (areMessagesRequested == false).
+     */
+    void requestingEntityScriptServerLog(bool areMessagesRequested);
+
 public slots:
 
     /*@jsdoc
@@ -406,9 +419,11 @@ protected:
     bool _defaultScriptsLocationOverridden { false };
     QString _debugScriptUrl;
 
-    // TODO: remove script managers when shutting them down
-    QSet<ScriptManagerPointer> _scriptManagersThatRequestedServerEntityMessages;
-    QMutex _serverEntityMessagesMutex;
+    // For subscriptions to server entity script messages
+    std::mutex _subscriptionsToEntityScriptMessagesMutex;
+    QSet<ScriptManager*> _managersSubscribedToEntityScriptMessages;
+    // Since multiple entity scripts run in the same script engine, there's a need to track subscriptions per entity
+    QHash<ScriptManager*, QSet<QUuid>> _entitiesSubscribedToEntityScriptMessages;
 
     // If this is set, defaultScripts.js will not be run if it is in the settings,
     // and this will be run instead. This script will not be persisted to settings.
diff --git a/libraries/script-engine/src/ScriptManagerScriptingInterface.cpp b/libraries/script-engine/src/ScriptManagerScriptingInterface.cpp
index d41b53660d..8c2d2799f3 100644
--- a/libraries/script-engine/src/ScriptManagerScriptingInterface.cpp
+++ b/libraries/script-engine/src/ScriptManagerScriptingInterface.cpp
@@ -91,16 +91,37 @@ void ScriptManagerScriptingInterface::stopProfilingAndSave() {
 }
 
 void ScriptManagerScriptingInterface::requestServerEntityScriptMessages() {
-    if (_manager->isEntityServerScript() || _manager->isEntityServerScript() || _manager->isClientScript()) {
+    if (_manager->isEntityServerScript() || _manager->isEntityServerScript()) {
+        _manager->engine()->raiseException("Uuid needs to be specified when requestServerEntityScriptMessages is invoked from entity script");
+    } else {
         auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
-        //TODO;
+        scriptEngines->requestServerEntityScriptMessages(_manager);
+    }
+}
+
+void ScriptManagerScriptingInterface::requestServerEntityScriptMessages(const QUuid& entityID) {
+    if (_manager->isEntityServerScript() || _manager->isEntityServerScript()) {
+        auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
+        scriptEngines->requestServerEntityScriptMessages(_manager, entityID);
+    } else {
+        _manager->engine()->raiseException("Uuid must not be specified when requestServerEntityScriptMessages is invoked from entity script");
     }
 }
 
 void ScriptManagerScriptingInterface::removeServerEntityScriptMessagesRequest() {
-    if (_manager->isEntityServerScript() || _manager->isEntityServerScript() || _manager->isClientScript()) {
+    if (_manager->isEntityServerScript() || _manager->isEntityServerScript()) {
+        _manager->engine()->raiseException("Uuid needs to be specified when removeServerEntityScriptMessagesRequest is invoked from entity script");
+    } else {
         auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
-        //TODO;
+        scriptEngines->removeServerEntityScriptMessagesRequest(_manager);
     }
 }
 
+void ScriptManagerScriptingInterface::removeServerEntityScriptMessagesRequest(const QUuid& entityID) {
+    if (_manager->isEntityServerScript() || _manager->isEntityServerScript()) {
+        auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
+        scriptEngines->removeServerEntityScriptMessagesRequest(_manager, entityID);
+    } else {
+        _manager->engine()->raiseException("Uuid must not be specified when removeServerEntityScriptMessagesRequest is invoked from entity script");
+    }
+}
diff --git a/libraries/script-engine/src/ScriptManagerScriptingInterface.h b/libraries/script-engine/src/ScriptManagerScriptingInterface.h
index 13cacb07fb..c1d6bad360 100644
--- a/libraries/script-engine/src/ScriptManagerScriptingInterface.h
+++ b/libraries/script-engine/src/ScriptManagerScriptingInterface.h
@@ -512,7 +512,7 @@ public:
 
     /*@jsdoc
      * Start collecting object statistics that can later be reported with Script.dumpHeapObjectStatistics().
-     * @function Script.dumpHeapObjectStatistics
+     * @function Script.startCollectingObjectStatistics
      */
     Q_INVOKABLE void startCollectingObjectStatistics();
 
@@ -562,18 +562,24 @@ public:
      * through signals such as errorEntityMessage. This function can be invoked both from client-side entity scripts
      * and from interface scripts.
      * @function Script.subscribeToServerEntityScriptMessages
+     * @param {Uuid=} entityID - The ID of the entity that requests entity server script messages. Only needs to be specified
+     * for entity scripts, and must not be specified for other types of scripts.
      */
 
      Q_INVOKABLE void requestServerEntityScriptMessages();
+     Q_INVOKABLE void requestServerEntityScriptMessages(const QUuid& entityID);
 
      /*@jsdoc
      * Calling this function signalizes that current script doesn't require stop receiving server-side entity script messages
      * through signals such as errorEntityMessage. This function can be invoked both from client-side entity scripts
      * and from interface scripts.
      * @function Script.unsubscribeFromServerEntityScriptMessages
+     * @param {Uuid=} entityID - The ID of the entity that requests entity server script messages. Only needs to be specified
+     * for entity scripts, and must not be specified for other types of scripts.
      */
 
      Q_INVOKABLE void removeServerEntityScriptMessagesRequest();
+     Q_INVOKABLE void removeServerEntityScriptMessagesRequest(const QUuid& entityID);
 
  signals: