diff --git a/src/metabase/api/card.clj b/src/metabase/api/card.clj
index 18c477a1570dfb3a65a412109a7b24ad3d0f282c..e27c8c855ce6dcc1e2143a40bf4663287d34e84f 100644
--- a/src/metabase/api/card.clj
+++ b/src/metabase/api/card.clj
@@ -3,6 +3,7 @@
             [clojure.tools.logging :as log]
             [cheshire.core :as json]
             [compojure.core :refer [GET POST DELETE PUT]]
+            [ring.util.codec :as codec]
             [schema.core :as s]
             (toucan [db :as db]
                     [hydrate :refer [hydrate]])
@@ -133,8 +134,18 @@
 (defn- ^:deprecated card-has-label? [label-slug card]
   (contains? (set (map :slug (:labels card))) label-slug))
 
+(defn- collection-slug->id [collection-slug]
+  (when (seq collection-slug)
+    ;; special characters in the slugs are always URL-encoded when stored in the DB, e.g.
+    ;; "Obsługa klienta" becomes "obs%C5%82uga_klienta". But for some weird reason sometimes the slug is passed in like
+    ;; "obsługa_klientaa" (not URL-encoded) so go ahead and URL-encode the input as well so we can match either case
+    (check-404 (db/select-one-id Collection
+                 {:where [:or [:= :slug collection-slug]
+                          [:= :slug (codec/url-encode collection-slug)]]}))))
+
 ;; TODO - do we need to hydrate the cards' collections as well?
-(defn- cards-for-filter-option [filter-option model-id label collection]
+(defn- cards-for-filter-option [filter-option model-id label collection-slug]
+  (println "collection-slug:" collection-slug) ; NOCOMMIT
   (let [cards (-> ((filter-option->fn (or filter-option :all)) model-id)
                   (hydrate :creator :collection)
                   hydrate-labels
@@ -142,11 +153,10 @@
     ;; Since labels and collections are hydrated in Clojure-land we need to wait until this point to apply label/collection filtering if applicable
     ;; COLLECTION can optionally be an empty string which is used to repre
     (filter (cond
-              collection  (let [collection-id (when (seq collection)
-                                                (check-404 (db/select-one-id Collection :slug collection)))]
-                            (comp (partial = collection-id) :collection_id))
-              (seq label) (partial card-has-label? label)
-              :else       identity)
+              collection-slug (let [collection-id (collection-slug->id collection-slug)]
+                                (comp (partial = collection-id) :collection_id))
+              (seq label)     (partial card-has-label? label)
+              :else           identity)
             cards)))
 
 
diff --git a/test/metabase/api/card_test.clj b/test/metabase/api/card_test.clj
index 74aef6f003f316ae826e9cd31d19419d92325db9..a42630ea44f06bb291c5756a1f8802529f291577 100644
--- a/test/metabase/api/card_test.clj
+++ b/test/metabase/api/card_test.clj
@@ -528,6 +528,22 @@
   "Not found."
   ((user->client :rasta) :get 404 "card/" :collection :some_fake_collection_slug))
 
+;; Make sure GET /api/card?collection=<slug> still works with Collections with URL-encoded Slugs (#4535)
+(expect
+  []
+  (tt/with-temp Collection [collection {:name "Obsługa klienta"}]
+    (do
+      (perms/grant-collection-readwrite-permissions! (perms-group/all-users) collection)
+      ((user->client :rasta) :get 200 "card/" :collection "obs%C5%82uga_klienta"))))
+
+;; ...even if the slug isn't passed in URL-encoded
+(expect
+  []
+  (tt/with-temp Collection [collection {:name "Obsługa klienta"}]
+    (do
+      (perms/grant-collection-readwrite-permissions! (perms-group/all-users) collection)
+      ((user->client :rasta) :get 200 "card/" :collection "obsługa_klienta"))))
+
 
 ;;; ------------------------------------------------------------ Bulk Collections Update (POST /api/card/collections) ------------------------------------------------------------