Index: src/org/openstreetmap/josm/actions/downloadtasks/DownloadReferrersTask.java
===================================================================
--- src/org/openstreetmap/josm/actions/downloadtasks/DownloadReferrersTask.java	(revision 15831)
+++ src/org/openstreetmap/josm/actions/downloadtasks/DownloadReferrersTask.java	(working copy)
@@ -7,7 +7,10 @@
 import java.io.IOException;
 import java.text.MessageFormat;
 import java.util.Collection;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -14,6 +17,7 @@
 import javax.swing.JOptionPane;
 import javax.swing.SwingUtilities;
 
+import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.DataSetMerger;
 import org.openstreetmap.josm.data.osm.Node;
@@ -30,8 +34,10 @@
 import org.openstreetmap.josm.io.OsmServerBackreferenceReader;
 import org.openstreetmap.josm.io.OsmServerReader;
 import org.openstreetmap.josm.io.OsmTransferException;
+import org.openstreetmap.josm.io.OverpassDownloadReader;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.ExceptionUtil;
+import org.openstreetmap.josm.tools.Logging;
 import org.xml.sax.SAXException;
 
 /**
@@ -150,37 +156,45 @@
     @Override
     protected void realRun() throws SAXException, IOException, OsmTransferException {
         try {
-            progressMonitor.setTicksCount(children.size());
-            int i = 1;
-            for (PrimitiveId p : children) {
-                if (canceled)
-                    return;
-                String msg;
-                String id = Long.toString(p.getUniqueId());
-                switch(p.getType()) {
-                case NODE: msg = tr("({0}/{1}) Loading parents of node {2}", i, children.size(), id); break;
-                case WAY: msg = tr("({0}/{1}) Loading parents of way {2}", i, children.size(), id); break;
-                case RELATION: msg = tr("({0}/{1}) Loading parents of relation {2}", i, children.size(), id); break;
-                default: throw new AssertionError();
+            if (Boolean.TRUE.equals(OverpassDownloadReader.FOR_MULTI_FETCH.get())) {
+                String request = genOverpassQuery();
+                OverpassDownloadReader reader = new OverpassDownloadReader(new Bounds(0, 0, 0, 0),
+                        OverpassDownloadReader.OVERPASS_SERVER.get(), request);
+                DataSet ds = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false));
+                new DataSetMerger(parents, ds).merge();
+            } else {
+                progressMonitor.setTicksCount(children.size());
+                int i = 1;
+                for (PrimitiveId p : children) {
+                    if (canceled)
+                        return;
+                    String msg;
+                    String id = Long.toString(p.getUniqueId());
+                    switch(p.getType()) {
+                    case NODE: msg = tr("({0}/{1}) Loading parents of node {2}", i, children.size(), id); break;
+                    case WAY: msg = tr("({0}/{1}) Loading parents of way {2}", i, children.size(), id); break;
+                    case RELATION: msg = tr("({0}/{1}) Loading parents of relation {2}", i, children.size(), id); break;
+                    default: throw new AssertionError();
+                    }
+                    progressMonitor.subTask(msg);
+                    downloadParents(p.getUniqueId(), p.getType(), progressMonitor);
+                    i++;
                 }
-                progressMonitor.subTask(msg);
-                downloadParents(p.getUniqueId(), p.getType(), progressMonitor);
-                i++;
-            }
-            Collection<Way> ways = parents.getWays();
+                Collection<Way> ways = parents.getWays();
 
-            if (!ways.isEmpty()) {
-                // Collect incomplete nodes of parent ways
-                Set<Node> nodes = ways.stream().flatMap(w -> w.getNodes().stream().filter(OsmPrimitive::isIncomplete))
-                        .collect(Collectors.toSet());
-                if (!nodes.isEmpty()) {
-                    reader = MultiFetchServerObjectReader.create();
-                    ((MultiFetchServerObjectReader) reader).append(nodes);
-                    DataSet wayNodes = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false));
-                    synchronized (this) { // avoid race condition in cancel()
-                        reader = null;
+                if (!ways.isEmpty()) {
+                    // Collect incomplete nodes of parent ways
+                    Set<Node> nodes = ways.stream().flatMap(w -> w.getNodes().stream().filter(OsmPrimitive::isIncomplete))
+                            .collect(Collectors.toSet());
+                    if (!nodes.isEmpty()) {
+                        reader = MultiFetchServerObjectReader.create();
+                        ((MultiFetchServerObjectReader) reader).append(nodes);
+                        DataSet wayNodes = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false));
+                        synchronized (this) { // avoid race condition in cancel()
+                            reader = null;
+                        }
+                        new DataSetMerger(parents, wayNodes).merge();
                     }
-                    new DataSetMerger(parents, wayNodes).merge();
                 }
             }
         } catch (OsmTransferException e) {
@@ -189,4 +203,55 @@
             lastException = e;
         }
     }
+
+    private String genOverpassQuery() {
+        Map<OsmPrimitiveType, Set<Long>> primitivesMap = new LinkedHashMap<>();
+        primitivesMap.put(OsmPrimitiveType.NODE, new LinkedHashSet<>());
+        primitivesMap.put(OsmPrimitiveType.WAY, new LinkedHashSet<>());
+        primitivesMap.put(OsmPrimitiveType.RELATION, new LinkedHashSet<>());
+        for (PrimitiveId p : children) {
+            primitivesMap.get(p.getType()).add(p.getUniqueId());
+        }
+        boolean getWays = false;
+        StringBuilder sb = new StringBuilder();
+        StringBuilder sets = new StringBuilder();
+        for (Entry<OsmPrimitiveType, Set<Long>> e : primitivesMap.entrySet()) {
+            if (!e.getValue().isEmpty()) {
+                String list = getPackageString(e.getKey(), e.getValue());
+                switch (e.getKey()) {
+                case NODE:
+                    sb.append('(').append(list).append("->.n;.n;rel(bn);.n;way(bn);)->.pn;");
+                    sets.append(".pn;");
+                    getWays = true;
+                    break;
+                case CLOSEDWAY:
+                case WAY:
+                    sb.append(list).append(";rel(bw)->.pw;");
+                    sets.append(".pw;");
+                    break;
+                case MULTIPOLYGON:
+                case RELATION:
+                    sb.append(list).append(";rel(br)->.pr;");
+                    sets.append(".pr;");
+                    break;
+                }
+            }
+        }
+        // retrieve all incomplete nodes for union of parents
+        if (getWays)
+            sb.append("((").append(sets).append(");node(w);node(r););");
+        else
+            sb.append("((").append(sets).append(");node(r););");
+        sb.append("out meta;");
+        String query = sb.toString();
+        Logging.debug("{0} {1}", "Generated Overpass query:", query);
+        return query;
+
+    }
+
+    private static String getPackageString(final OsmPrimitiveType type, Set<Long> idPackage) {
+        return idPackage.stream().map(String::valueOf)
+                .collect(Collectors.joining(",", type.getAPIName() + (idPackage.size() == 1 ? "(" : "(id:"), ")"));
+    }
+
 }
Index: src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java
===================================================================
--- src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java	(revision 15831)
+++ src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java	(working copy)
@@ -434,7 +434,7 @@
                 if (isCanceled())
                     return null;
                 OverpassDownloadReader reader = new OverpassDownloadReader(new Bounds(0, 0, 0, 0), getBaseUrl(), request);
-                DataSet ds = reader.parseOsm(progressMonitor.createSubTaskMonitor(n, false));
+                DataSet ds = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false));
                 new DataSetMerger(outputDataSet, ds).merge();
                 checkMissing(outputDataSet, progressMonitor);
             } else {
