diff --git a/builtin/mainmenu/tab_credits.lua b/builtin/mainmenu/tab_credits.lua
index 4d2ffd7f4713d5871cd8ff28db59549a57415878..9b6045263ef9bd5174c2b272416de3d07fee36da 100644
--- a/builtin/mainmenu/tab_credits.lua
+++ b/builtin/mainmenu/tab_credits.lua
@@ -76,8 +76,9 @@ return {
 	caption = fgettext("Credits"),
 	cbf_formspec = function(tabview, name, tabdata)
 		local logofile = defaulttexturedir .. "logo.png"
+		local version = core.get_version()
 		return "image[0.5,1;" .. core.formspec_escape(logofile) .. "]" ..
-			"label[0.5,3.2;Minetest " .. core.get_version() .. "]" ..
+			"label[0.5,3.2;" .. version.project .. " " .. version.string .. "]" ..
 			"label[0.5,3.5;http://minetest.net]" ..
 			"tablecolumns[color;text]" ..
 			"tableoptions[background=#00000000;highlight=#00000000;border=false]" ..
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index da90f93d2655e2c295eb5c577d5f1d38a6b600c1..497864fac5669d99808c600bd6d8ad3a91d3b47c 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -1908,6 +1908,17 @@ Helper functions
       * nil: return all entries,
       * true: return only subdirectory names, or
       * false: return only file names.
+* `minetest.get_version()`: returns a table containing components of the
+   engine version.  Components:
+    * `project`: Name of the project, eg, "Minetest"
+    * `string`: Simple version, eg, "1.2.3-dev"
+    * `hash`: Full git version (only set if available), eg, "1.2.3-dev-01234567-dirty"
+  Use this for informational purposes only. The information in the returned
+  table does not represent the capabilities of the engine, nor is it
+  reliable or verifyable. Compatible forks will have a different name and
+  version entirely. To check for the presence of engine features, test
+  whether the functions exported by the wanted features exist. For example:
+  `if core.nodeupdate then ... end`.
 
 ### Logging
 * `minetest.debug(...)`
diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp
index 8b078eafd20ec371cb878f3ab1bade331623ca5f..4a2484613f790ff439249a29ad8a120df2f82aa6 100644
--- a/src/script/lua_api/l_mainmenu.cpp
+++ b/src/script/lua_api/l_mainmenu.cpp
@@ -955,13 +955,6 @@ int ModApiMainMenu::l_show_file_open_dialog(lua_State *L)
 	return 0;
 }
 
-/******************************************************************************/
-int ModApiMainMenu::l_get_version(lua_State *L)
-{
-	lua_pushstring(L, g_version_string);
-	return 1;
-}
-
 /******************************************************************************/
 int ModApiMainMenu::l_sound_play(lua_State *L)
 {
@@ -1157,7 +1150,6 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
 	API_FCT(extract_zip);
 	API_FCT(get_mainmenu_path);
 	API_FCT(show_file_open_dialog);
-	API_FCT(get_version);
 	API_FCT(download_file);
 	API_FCT(get_modstore_details);
 	API_FCT(get_modstore_list);
@@ -1188,7 +1180,6 @@ void ModApiMainMenu::InitializeAsync(AsyncEngine& engine)
 	ASYNC_API_FCT(delete_dir);
 	ASYNC_API_FCT(copy_dir);
 	//ASYNC_API_FCT(extract_zip); //TODO remove dependency to GuiEngine
-	ASYNC_API_FCT(get_version);
 	ASYNC_API_FCT(download_file);
 	ASYNC_API_FCT(get_modstore_details);
 	ASYNC_API_FCT(get_modstore_list);
diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h
index 405af25e8a1380a9d9df088f2afe5d93a2a41b28..ad5155ac6a77026c45d8820e8f17cc73c9e45eb5 100644
--- a/src/script/lua_api/l_mainmenu.h
+++ b/src/script/lua_api/l_mainmenu.h
@@ -79,8 +79,6 @@ class ModApiMainMenu : public ModApiBase {
 
 	static int l_delete_favorite(lua_State *L);
 
-	static int l_get_version(lua_State *L);
-
 	static int l_sound_play(lua_State *L);
 
 	static int l_sound_stop(lua_State *L);
diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp
index fa2d15b03379663f10e5c5636659e34957316120..818c1aeeb2f580097f375b45f3ad5135b38b8855 100644
--- a/src/script/lua_api/l_util.cpp
+++ b/src/script/lua_api/l_util.cpp
@@ -33,8 +33,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "settings.h"
 #include "util/auth.h"
 #include "util/base64.h"
+#include "config.h"
+#include "version.h"
 #include <algorithm>
 
+
 // log([level,] text)
 // Writes a line to the logger.
 // The one-argument version logs to infostream.
@@ -302,12 +305,14 @@ int ModApiUtil::l_is_yes(lua_State *L)
 	return 1;
 }
 
+// get_builtin_path()
 int ModApiUtil::l_get_builtin_path(lua_State *L)
 {
 	NO_MAP_LOCK_REQUIRED;
 
 	std::string path = porting::path_share + DIR_DELIM + "builtin";
 	lua_pushstring(L, path.c_str());
+
 	return 1;
 }
 
@@ -460,6 +465,26 @@ int ModApiUtil::l_request_insecure_environment(lua_State *L)
 	return 1;
 }
 
+// get_version()
+int ModApiUtil::l_get_version(lua_State *L)
+{
+	lua_createtable(L, 0, 3);
+	int table = lua_gettop(L);
+
+	lua_pushstring(L, PROJECT_NAME_C);
+	lua_setfield(L, table, "project");
+
+	lua_pushstring(L, g_version_string);
+	lua_setfield(L, table, "string");
+
+	if (strcmp(g_version_string, g_version_hash)) {
+		lua_pushstring(L, g_version_hash);
+		lua_setfield(L, table, "hash");
+	}
+
+	return 1;
+}
+
 
 void ModApiUtil::Initialize(lua_State *L, int top)
 {
@@ -496,6 +521,8 @@ void ModApiUtil::Initialize(lua_State *L, int top)
 
 	API_FCT(encode_base64);
 	API_FCT(decode_base64);
+
+	API_FCT(get_version);
 }
 
 void ModApiUtil::InitializeAsync(AsyncEngine& engine)
@@ -525,5 +552,7 @@ void ModApiUtil::InitializeAsync(AsyncEngine& engine)
 
 	ASYNC_API_FCT(encode_base64);
 	ASYNC_API_FCT(decode_base64);
+
+	ASYNC_API_FCT(get_version);
 }
 
diff --git a/src/script/lua_api/l_util.h b/src/script/lua_api/l_util.h
index 3012d55aa2a593f93d6a31cdae1e11ce4dbe718e..9910704b37d96accfbe365326debb0cf1b745fb9 100644
--- a/src/script/lua_api/l_util.h
+++ b/src/script/lua_api/l_util.h
@@ -104,6 +104,9 @@ class ModApiUtil : public ModApiBase {
 	// decode_base64(string)
 	static int l_decode_base64(lua_State *L);
 
+	// get_version()
+	static int l_get_version(lua_State *L);
+
 public:
 	static void Initialize(lua_State *L, int top);