diff --git a/lib/libfetch/fetch.c b/lib/libfetch/fetch.c
index 82a3c5e451a..eed466018e3 100644
--- a/lib/libfetch/fetch.c
+++ b/lib/libfetch/fetch.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
 
 #include <errno.h>
 #include <ctype.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -443,15 +444,25 @@ fetchParseURL(const char *URL)
 	if (strcmp(u->scheme, SCHEME_HTTP) == 0 ||
 	    strcmp(u->scheme, SCHEME_HTTPS) == 0) {
 		const char hexnums[] = "0123456789abcdef";
+		bool in_query_string = false;
 
 		/* percent-escape whitespace. */
+		/* Some servers do not handle '+' properly. In the path it must be
+		 * literal. In the query string it can be an encoded space.
+		 * Percent-escape the '+' in the path to be unambiguous to the server.
+		 * https://www.w3.org/Addressing/URL/4_URI_Recommentations.html
+		 * https://forums.aws.amazon.com/thread.jspa?threadID=55746
+		 */
 		if ((doc = malloc(strlen(p) * 3 + 1)) == NULL) {
 			fetch_syserr();
 			goto ouch;
 		}
 		u->doc = doc;
 		while (*p != '\0') {
-			if (!isspace((unsigned char)*p)) {
+			if (*p == '?') {
+				in_query_string = true;
+			}
+			if (!isspace((unsigned char)*p) && (in_query_string || *p != '+')) {
 				*doc++ = *p++;
 			} else {
 				*doc++ = '%';