diff --git a/src/box/box_lua.m b/src/box/box_lua.m
index ea505c424c7879367a5c055a2a40e53945b28980..e6956e33b1087abc6441154d0b8c3bb07e23e69a 100644
--- a/src/box/box_lua.m
+++ b/src/box/box_lua.m
@@ -1012,8 +1012,8 @@ lua_table_to_tuple(struct lua_State *L, int index)
 	return tuple;
 }
 
-static void
-port_add_lua_ret(struct port *port, struct lua_State *L, int index)
+static struct tuple*
+lua_totuple(struct lua_State *L, int index)
 {
 	int type = lua_type(L, index);
 	struct tuple *tuple;
@@ -1073,6 +1073,13 @@ port_add_lua_ret(struct port *port, struct lua_State *L, int index)
 		tnt_raise(ClientError, :ER_PROC_RET, lua_typename(L, type));
 		break;
 	}
+	return tuple;
+}
+
+static void
+port_add_lua_ret(struct port *port, struct lua_State *L, int index)
+{
+	struct tuple *tuple = lua_totuple(L, index);
 	@try {
 		port_add_tuple(port, tuple, BOX_RETURN_TUPLE);
 	} @finally {
@@ -1144,8 +1151,20 @@ static int lbox_process(lua_State *L)
 	return lua_gettop(L) - top;
 }
 
+static int
+lbox_totuple(lua_State *L)
+{
+	int argc = lua_gettop(L);
+	if (argc < 1)
+		luaL_error(L, "box.totuple(): bad arguments");
+	struct tuple *tuple = lua_totuple(L, 1);
+	lbox_pushtuple(L, tuple);
+	return 1;
+}
+
 static const struct luaL_reg boxlib[] = {
 	{"process", lbox_process},
+	{"totuple", lbox_totuple},
 	{NULL, NULL}
 };
 
diff --git a/test/box/lua.result b/test/box/lua.result
index 429192fad9f45fa5a4a1f06108f5c440b317a94c..8ae5254177e379f0b1df4955d5da163ab996ee1e 100644
--- a/test/box/lua.result
+++ b/test/box/lua.result
@@ -13,31 +13,32 @@ lua print('  lua says: hello')
 lua for n in pairs(box) do print('  - box.', n) end
 ---
   - box.fiber
-  - box.select_reverse_range
+  - box.totuple
   - box.uuid
   - box.ipc
   - box.delete
-  - box.replace
   - box.space
+  - box.replace
   - box.cfg
   - box.on_reload_configuration
+  - box.counter
   - box.select_range
   - box.insert
-  - box.counter
   - box.auto_increment
+  - box.update
   - box.info
   - box.session
   - box.uuid_hex
-  - box.update
+  - box.select_reverse_range
   - box.dostring
   - box.process
-  - box.select_limit
-  - box.slab
   - box.select
+  - box.select_limit
+  - box.stat
   - box.flags
   - box.unpack
+  - box.slab
   - box.index
-  - box.stat
   - box.pack
 ...
 lua box.pack()
@@ -1731,3 +1732,24 @@ lua tostring(tonumber64(tonumber64(3)))
 ---
  - 3ULL
 ...
+# box.totuple test
+lua box.totuple()
+---
+error: 'box.totuple(): bad arguments'
+...
+lua box.totuple(1)
+---
+ - 1: {}
+...
+lua box.totuple('string')
+---
+ - 'string': {}
+...
+lua box.totuple(tonumber64('18446744073709551615'))
+---
+ - 18446744073709551615: {}
+...
+lua box.totuple({tonumber64('18446744073709551615'), 'string', 1})
+---
+ - 18446744073709551615: {'string', 1}
+...
diff --git a/test/box/lua.test b/test/box/lua.test
index 5b869eb5ed4ad752d8263ce2f31ef8cc621cc488..e32c77e3986fbeb80cf3acccefa69da3f3cf0e47 100644
--- a/test/box/lua.test
+++ b/test/box/lua.test
@@ -577,3 +577,10 @@ exec admin "lua bit.bor(1, 2)"
 print """# A test case for Bug#1061747 'tonumber64 is not transitive'"""
 exec admin "lua tonumber64(tonumber64(2))"
 exec admin "lua tostring(tonumber64(tonumber64(3)))"
+
+print """# box.totuple test"""
+exec admin "lua box.totuple()"
+exec admin "lua box.totuple(1)"
+exec admin "lua box.totuple('string')"
+exec admin "lua box.totuple(tonumber64('18446744073709551615'))"
+exec admin "lua box.totuple({tonumber64('18446744073709551615'), 'string', 1})"