Index: src/org/openstreetmap/josm/io/remotecontrol/AddTagsDialog.java
===================================================================
--- src/org/openstreetmap/josm/io/remotecontrol/AddTagsDialog.java	(revision 19570)
+++ src/org/openstreetmap/josm/io/remotecontrol/AddTagsDialog.java	(working copy)
@@ -283,7 +283,7 @@
      * @since 15316
      */
     public static Map<String, String> parseUrlTagsToKeyValues(String urlSection) {
-        Map<String, String> tags = TextTagParser.readTagsByRegexp(urlSection, "\\|", "(.*?)=(.*?)", false);
+        Map<String, String> tags = TextTagParser.readTagsByRegexp(urlSection, "(?<!\\\\)\\|", "(.*?)=(.*?)", false, true);
         return tags == null ? Collections.emptyMap() : tags;
     }
 
Index: src/org/openstreetmap/josm/tools/TextTagParser.java
===================================================================
--- src/org/openstreetmap/josm/tools/TextTagParser.java	(revision 19570)
+++ src/org/openstreetmap/josm/tools/TextTagParser.java	(working copy)
@@ -46,9 +46,10 @@
      * @param splitRegex - text is split into parts with this delimiter
      * @param tagRegex - each part is matched against this regex
      * @param unescapeTextInQuotes - if true, matched tag and value will be analyzed more thoroughly
+     * @param unescapePipe - if true, then replace all '\|' by '|' (issue #14490)
      * @return map of tags
      */
-    public static Map<String, String> readTagsByRegexp(String text, String splitRegex, String tagRegex, boolean unescapeTextInQuotes) {
+    public static Map<String, String> readTagsByRegexp(String text, String splitRegex, String tagRegex, boolean unescapeTextInQuotes, boolean unescapePipe) {
          String[] lines = text.split(splitRegex, -1);
          Pattern p = Pattern.compile(tagRegex);
          Map<String, String> tags = new LinkedHashMap<>();
@@ -65,6 +66,10 @@
                      v = unescape(v);
                      if (k == null || v == null) return null;
                  }
+                 if (unescapePipe) {
+                     k = k.replaceAll("\\\\\\|","|");
+                     v = v.replaceAll("\\\\\\|","|");
+                 }
                  tags.put(k, v);
             } else {
                 return null;
@@ -99,7 +104,7 @@
 
         // Format
         // tag1\tval1\ntag2\tval2\n
-        tags = readTagsByRegexp(buf, "[\\r\\n]+", ".*?([a-zA-Z0-9:_]+).*\\t(.*?)", false);
+        tags = readTagsByRegexp(buf, "[\\r\\n]+", ".*?([a-zA-Z0-9:_]+).*\\t(.*?)", false, false);
         // try "tag\tvalue\n" format
         if (tags != null) return tags;
 
@@ -108,7 +113,7 @@
         // SORRY: "a=b" = c is not supported for now, only first = will be considered
         // a = "b=c" is OK
         // a = b=c  - this method of parsing fails intentionally
-        tags = readTagsByRegexp(buf, "[\\n\\t\\r]+", "(.*?)=(.*?)", true);
+        tags = readTagsByRegexp(buf, "[\\n\\t\\r]+", "(.*?)=(.*?)", true, false );
         // try format  t1=v1\n t2=v2\n ...
         if (tags != null) return tags;
 
@@ -118,7 +123,7 @@
         if (bufJson.startsWith("{") && bufJson.endsWith("}"))
             bufJson = bufJson.substring(1, bufJson.length()-1);
         tags = readTagsByRegexp(bufJson, "[\\s]*,[\\s]*",
-                "[\\s]*(\\\".*?[^\\\\]\\\")"+"[\\s]*:[\\s]*"+"(\\\".*?[^\\\\]\\\")[\\s]*", true);
+                "[\\s]*(\\\".*?[^\\\\]\\\")"+"[\\s]*:[\\s]*"+"(\\\".*?[^\\\\]\\\")[\\s]*", true, false);
         if (tags != null) return tags;
 
         // Free format
Index: test/unit/org/openstreetmap/josm/io/remotecontrol/AddTagsDialogTest.java
===================================================================
--- test/unit/org/openstreetmap/josm/io/remotecontrol/AddTagsDialogTest.java	(revision 19570)
+++ test/unit/org/openstreetmap/josm/io/remotecontrol/AddTagsDialogTest.java	(working copy)
@@ -23,4 +23,46 @@
         assertEquals("Residenzschloss Dresden", strings.get("wikipedia:de"));
         assertEquals("Dresden Castle", strings.get("name:en"));
     }
+
+    /**
+     * Unit test for issue #14490 "Support for escaping pipe character in remote control addtags parameters"
+     * A single URL section (value of addtags=...) with a single escaped pipe sysmbol
+     */
+    @Test
+    void testParseUrlTagsToKeyValues_OneKeyValuePair_OneEscapedPipe() {
+        Map<String, String> strings = AddTagsDialog.parseUrlTagsToKeyValues("gtfs:route_id=de:mvv-muenchen:19-210\\|210");
+        assertEquals(1, strings.size());
+        assertEquals("de:mvv-muenchen:19-210|210", strings.get("gtfs:route_id"));
+    }
+
+    /**
+     * Unit test for issue #14490 "Support for escaping pipe character in remote control addtags parameters"
+     * A single URL section (value of addtags=...) with two escaped pipe sysmbols
+     */
+    @Test
+    void testParseUrlTagsToKeyValues_OneKeyValuePair_TwoEscapedPipe() {
+        Map<String, String> strings = AddTagsDialog.parseUrlTagsToKeyValues("gtfs:route_id=de:mvv-muenchen:19-210\\|210\\|RegionalBus:1179_3");
+        assertEquals(1, strings.size());
+        assertEquals("de:mvv-muenchen:19-210|210|RegionalBus:1179_3", strings.get("gtfs:route_id"));
+    }
+    /**
+     * Unit test for issue #14490 "Support for escaping pipe character in remote control addtags parameters"
+     * Two URL sections (values of addtags=...) with a single escaped pipe sysmbol each
+     */
+    @Test
+    void testParseUrlTagsToKeyValues_TwoKeyValuePairs_FourEscapedPipe() {
+        Map<String, String> strings = AddTagsDialog.parseUrlTagsToKeyValues("gtfs:route_id=de:mvv-muenchen:19-210\\|210\\|RegionalBus:1179_3|gtfs:trip_id:sample=de:mvv-muenchen:19-210\\|210\\|RegionalBus:1179-1-1-H-0-We#3-320-333");
+        assertEquals(2, strings.size());
+        assertEquals("de:mvv-muenchen:19-210|210|RegionalBus:1179_3", strings.get("gtfs:route_id"));
+        assertEquals("de:mvv-muenchen:19-210|210|RegionalBus:1179-1-1-H-0-We#3-320-333", strings.get("gtfs:trip_id:sample"));
+    }
+    /**
+     * Unit test for issue #14490 "Support for escaping pipe character in remote control addtags parameters"
+     * Two URL sections (values of addtags=...) with four un escaped pipe sysmbols in the value parts
+     */
+    @Test
+    void testParseUrlTagsToKeyValues_PipeInValue_NoEscapedPipe() {
+        Map<String, String> strings = AddTagsDialog.parseUrlTagsToKeyValues("gtfs:route_id=de:mvv-muenchen:19-210|210|RegionalBus:1179_3|gtfs:trip_id:sample=de:mvv-muenchen:19-210|210|RegionalBus:1179-1-1-H-0-We#3-320-333");
+        assertEquals(0, strings.size());
+    }
 }
Index: test/unit/org/openstreetmap/josm/tools/TextTagParserTest.java
===================================================================
--- test/unit/org/openstreetmap/josm/tools/TextTagParserTest.java	(revision 19570)
+++ test/unit/org/openstreetmap/josm/tools/TextTagParserTest.java	(working copy)
@@ -175,7 +175,7 @@
     void testStableOrder() {
         List<String> expected = Arrays.asList("foo4", "foo3", "foo2", "foo1");
         ArrayList<String> actual = new ArrayList<>(TextTagParser.readTagsByRegexp(
-                "foo4=bar4 foo3=bar3 foo2=bar2 foo1=bar1", " ", "(.*?)=(.*?)", true).keySet());
+                "foo4=bar4 foo3=bar3 foo2=bar2 foo1=bar1", " ", "(.*?)=(.*?)", true, false).keySet());
         assertEquals(expected, actual);
     }
 }
