diff --git a/scribus/plugins/scriptplugin/cmdmani.cpp b/scribus/plugins/scriptplugin/cmdmani.cpp
index ce0ea2ba3eee7cc56b3bba9b615ac95df82a8a9f..4c6ceec57659598fcbb232d2ca9193fcea6278c8 100644
--- a/scribus/plugins/scriptplugin/cmdmani.cpp
+++ b/scribus/plugins/scriptplugin/cmdmani.cpp
@@ -12,6 +12,7 @@ for which a new license (GPL+exception) is in place.
 #include "sctextstream.h"
 #include "selection.h"
 #include "undomanager.h"
+#include <QQueue>
 
 PyObject *scribus_loadimage(PyObject* /* self */, PyObject* args)
 {
@@ -451,6 +452,62 @@ PyObject *scribus_scalegroup(PyObject* /* self */, PyObject* args)
 	Py_RETURN_NONE;
 }
 
+PyObject *scribus_getGroupItems(PyObject * /*self*/, PyObject* args, PyObject* kw)
+{
+	if (!checkHaveDocument())
+		return nullptr;
+
+	char *name = const_cast<char*>("");
+	unsigned int recursive = 0;
+	unsigned int type = 0;
+	char* kwargs[] = {const_cast<char*>("name"), const_cast<char*>("recursive"), const_cast<char*>("type"), nullptr};
+	if (!PyArg_ParseTupleAndKeywords(args, kw, "|espi", kwargs, "utf-8", &name, &recursive, &type))
+		return nullptr;
+
+	PageItem *pageItem = GetUniqueItem(QString::fromUtf8(name));
+	if (pageItem == nullptr)
+		return nullptr;
+
+	if (!pageItem->isGroup())
+		return nullptr;
+
+	auto items = PyList_New(0);
+
+	QQueue<PageItem*> queue;
+	queue.enqueue(pageItem);
+
+	while (!queue.isEmpty())
+	{
+		const auto pageItem = queue.dequeue();
+		for (auto groupItem: pageItem->groupItemList)
+		{
+			if (recursive && groupItem->isGroup())
+			{
+				queue.enqueue(groupItem);
+				continue;
+			}
+			if (type == 0 || groupItem->itemType() == type) {
+				auto itemDict = PyDict_New();
+				PyDict_SetItem(itemDict,
+					PyUnicode_FromString("name"),
+					PyUnicode_FromString(groupItem->itemName().toUtf8().constData())
+				);
+				PyDict_SetItem(itemDict,
+					PyUnicode_FromString("type"),
+					PyLong_FromUnsignedLong((unsigned long) groupItem->itemType())
+				);
+				PyDict_SetItem(itemDict,
+					PyUnicode_FromString("order"),
+					PyLong_FromUnsignedLong((unsigned long) groupItem->uniqueNr)
+				);
+				PyList_Append(items, itemDict);
+			}
+		}
+	}
+
+	return items;
+}
+
 PyObject *scribus_getselectedobject(PyObject* /* self */, PyObject* args)
 {
 	int i = 0;
@@ -707,6 +764,7 @@ void cmdmanidocwarnings()
 	s << scribus_combinepolygons__doc__
 	  << scribus_deselectall__doc__
 	  << scribus_flipobject__doc__
+	  << scribus_getGroupItems__doc__
 	  << scribus_getselectedobject__doc__
 	  << scribus_groupobjects__doc__
 	  << scribus_islocked__doc__
diff --git a/scribus/plugins/scriptplugin/cmdmani.h b/scribus/plugins/scriptplugin/cmdmani.h
index e4d4253a74c17fd8b3f2c3de175932446c1439a3..f42d53bc83dbf2cc9463cc89b0c37451d78894c4 100644
--- a/scribus/plugins/scriptplugin/cmdmani.h
+++ b/scribus/plugins/scriptplugin/cmdmani.h
@@ -148,6 +148,21 @@ May raise ValueError if an invalid scale factor is passed.\n\
 /*! Scale group with object name */
 PyObject *scribus_scalegroup(PyObject * /*self*/, PyObject* args);
 
+/*! docstring */
+PyDoc_STRVAR(scribus_getGroupItems__doc__,
+QT_TR_NOOP("getGroupItems([\"name\", recursive=False, type=0]) -> [dict]\n\n\
+Return the list of items in the group.\n\
+\n\
+`recursive`: if True and some of the items are groups, also include their items (recursively).\n\
+`type`: if not 0, only retain items of this type.\n\
+\n\
+Each item is defined as a dictionary containing:\n\
+`{'name': str, 'type': int, 'order': int}`\n\
+\n\
+If \"name\" is not given the currently selected item is used."));
+/*! List the items in a group. */
+PyObject *scribus_getGroupItems(PyObject * /*self*/, PyObject* args, PyObject* kw);
+
 /*! docstring */
 PyDoc_STRVAR(scribus_loadimage__doc__,
 QT_TR_NOOP("loadImage(\"filename\" [, \"name\"])\n\
diff --git a/scribus/plugins/scriptplugin/scriptplugin.cpp b/scribus/plugins/scriptplugin/scriptplugin.cpp
index 2836dfb9672dd54a06ee5ff98f8084e54a9b9f7c..a5ca29ba30deefebb0b42374c4154a98eb65366b 100644
--- a/scribus/plugins/scriptplugin/scriptplugin.cpp
+++ b/scribus/plugins/scriptplugin/scriptplugin.cpp
@@ -364,6 +364,7 @@ PyMethodDef scribus_methods[] = {
 	{const_cast<char*>("getFontNames"), (PyCFunction)scribus_getfontnames, METH_NOARGS, tr(scribus_getfontnames__doc__)},
 	{const_cast<char*>("getFontSize"), scribus_getfontsize, METH_VARARGS, tr(scribus_getfontsize__doc__)},
 	{const_cast<char*>("getFrameText"), scribus_getframetext, METH_VARARGS, tr(scribus_getframetext__doc__)},
+	{const_cast<char*>("getGroupItems"), (PyCFunction)scribus_getGroupItems, METH_VARARGS|METH_KEYWORDS, tr(scribus_getGroupItems__doc__)},
 	{const_cast<char*>("getGuiLanguage"), (PyCFunction)scribus_getlanguage, METH_NOARGS, tr(scribus_getlanguage__doc__)},
 	{const_cast<char*>("getHGuides"), (PyCFunction)scribus_getHguides, METH_NOARGS, tr(scribus_getHguides__doc__)},
 	{const_cast<char*>("getImageColorSpace"), scribus_getimagecolorspace, METH_VARARGS, tr(scribus_getimagecolorspace__doc__) },
