diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # arch-web
 
+# 0.3.2
+
+* Use template haskell to generate SPDX license data type based on `data/KNOWN-SPDX.json`
+* Remove some dependency bounds
+* Breaking change: `licenseId (Custom "x")` now returns `"x"` instead of `"custom: x"`. This ensures that `licenseId (parseLicense x) == x` for all `x`.
+
 ## 0.3.1
 
 Fix typo in license
diff --git a/arch-web.cabal b/arch-web.cabal
--- a/arch-web.cabal
+++ b/arch-web.cabal
@@ -1,59 +1,55 @@
-cabal-version:   2.2
-name:            arch-web
-version:         0.3.1
-synopsis:        Arch Linux official and AUR web interface binding
+cabal-version:      2.2
+name:               arch-web
+version:            0.3.2
+synopsis:           Arch Linux official and AUR web interface binding
 description:
   Arch Linux official and AUR web interface binding.
   See README for details.
 
-category:        Web
-license:         MIT
-license-file:    LICENSE
-author:          berberman
-maintainer:      berberman <berberman@yandex.com>
-copyright:       Copyright (c) berberman 2021
-stability:       alpha
-homepage:        https://github.com/berberman/arch-web
-bug-reports:     https://github.com/berberman/arch-web/issues
+extra-source-files: data/KNOWN_SPDX.json
+category:           Web
+license:            MIT
+license-file:       LICENSE
+author:             berberman
+maintainer:         berberman <berberman@yandex.com>
+copyright:          Copyright (c) berberman 2020-2025
+stability:          alpha
+homepage:           https://github.com/berberman/arch-web
+bug-reports:        https://github.com/berberman/arch-web/issues
 extra-doc-files:
   CHANGELOG.md
   README.md
 
-tested-with:     GHC ==8.10.7 || ==9.0.2
+tested-with:        GHC ==9.2.8 || ==9.8.4
 
 common common
   build-depends:
-    , aeson                ^>=1.5.4  || ^>=2.0   || ^>=2.1 || ^>=2.2
+    , aeson                ^>=1.5.4  || ^>=2.0 || ^>=2.1 || ^>=2.2
     , base                 >=4.10    && <5
-    , deriving-aeson       ^>=0.2.6
-    , exceptions           ^>=0.10.4
-    , http-client          ^>=0.6.4  || ^>=0.7.4
-    , http-client-tls      ^>=0.3.5
-    , http-types           ^>=0.12.3
-    , lens                 ^>=4.19.2 || ^>=5     || ^>=5.1 || ^>=5.2
+    , bytestring
+    , containers
+    , deriving-aeson       ^>=0.2
+    , directory
+    , exceptions           ^>=0.10
+    , filepath
+    , http-client          ^>=0.6    || ^>=0.7
+    , http-client-tls      ^>=0.3
+    , http-types           ^>=0.12
+    , lens                 ^>=4.19.2 || ^>=5   || ^>=5.1 || ^>=5.2 || ^>=5.3
     , mtl
     , servant              >=0.18    && <0.21
     , servant-client       >=0.18    && <0.21
     , servant-client-core  >=0.18    && <0.21
+    , template-haskell     >=2.18
     , text
     , time
 
   default-language:   Haskell2010
   ghc-options:
     -Wall -Wcompat -Widentities -Wincomplete-uni-patterns
-    -Wincomplete-record-updates
-
-  if impl(ghc >=8.0)
-    ghc-options: -Wredundant-constraints
-
-  if impl(ghc >=8.2)
-    ghc-options: -fhide-source-paths
-
-  if impl(ghc >=8.4)
-    ghc-options: -Wmissing-export-lists
-
-  if impl(ghc >=8.8)
-    ghc-options: -Wmissing-deriving-strategies
+    -Wincomplete-record-updates -Wredundant-constraints
+    -fhide-source-paths -Wmissing-export-lists
+    -Wmissing-deriving-strategies
 
   default-extensions:
     ConstraintKinds
@@ -85,7 +81,10 @@
     Web.ArchLinux.Types
     Web.ArchLinux.Types.Lens
 
-  other-modules:   Web.ArchLinux.Types.API
+  other-modules:
+    Web.ArchLinux.Internal.KnownSPDXLoader
+    Web.ArchLinux.Types.API
+
   hs-source-dirs:  src
 
 test-suite arch-web-test
diff --git a/data/KNOWN_SPDX.json b/data/KNOWN_SPDX.json
new file mode 100644
--- /dev/null
+++ b/data/KNOWN_SPDX.json
@@ -0,0 +1,630 @@
+{
+    "0BSD": "N_0BSD",
+    "3D-Slicer-1.0": "N_3D_Slicer_1_0",
+    "AAL": "AAL",
+    "Abstyles": "Abstyles",
+    "AdaCore-doc": "AdaCore_doc",
+    "Adobe-2006": "Adobe_2006",
+    "Adobe-Display-PostScript": "Adobe_Display_PostScript",
+    "Adobe-Glyph": "Adobe_Glyph",
+    "Adobe-Utopia": "Adobe_Utopia",
+    "ADSL": "ADSL",
+    "AFL-1.1": "AFL_1_1",
+    "AFL-1.2": "AFL_1_2",
+    "AFL-2.0": "AFL_2_0",
+    "AFL-2.1": "AFL_2_1",
+    "AFL-3.0": "AFL_3_0",
+    "Afmparse": "Afmparse",
+    "AGPL-1.0-only": "AGPL_1_0_only",
+    "AGPL-1.0-or-later": "AGPL_1_0_or_later",
+    "AGPL-3.0-only": "AGPL_3_0_only",
+    "AGPL-3.0-or-later": "AGPL_3_0_or_later",
+    "Aladdin": "Aladdin",
+    "AMD-newlib": "AMD_newlib",
+    "AMDPLPA": "AMDPLPA",
+    "AML": "AML",
+    "AML-glslang": "AML_glslang",
+    "AMPAS": "AMPAS",
+    "ANTLR-PD": "ANTLR_PD",
+    "ANTLR-PD-fallback": "ANTLR_PD_fallback",
+    "any-OSI": "Any_OSI",
+    "Apache-1.0": "Apache_1_0",
+    "Apache-1.1": "Apache_1_1",
+    "Apache-2.0": "Apache_2_0",
+    "APAFML": "APAFML",
+    "APL-1.0": "APL_1_0",
+    "App-s2p": "App_s2p",
+    "APSL-1.0": "APSL_1_0",
+    "APSL-1.1": "APSL_1_1",
+    "APSL-1.2": "APSL_1_2",
+    "APSL-2.0": "APSL_2_0",
+    "Arphic-1999": "Arphic_1999",
+    "Artistic-1.0": "Artistic_1_0",
+    "Artistic-1.0-cl8": "Artistic_1_0_cl8",
+    "Artistic-1.0-Perl": "Artistic_1_0_Perl",
+    "Artistic-2.0": "Artistic_2_0",
+    "ASWF-Digital-Assets-1.0": "ASWF_Digital_Assets_1_0",
+    "ASWF-Digital-Assets-1.1": "ASWF_Digital_Assets_1_1",
+    "Baekmuk": "Baekmuk",
+    "Bahyph": "Bahyph",
+    "Barr": "Barr",
+    "bcrypt-Solar-Designer": "Bcrypt_Solar_Designer",
+    "Beerware": "Beerware",
+    "Bitstream-Charter": "Bitstream_Charter",
+    "Bitstream-Vera": "Bitstream_Vera",
+    "BitTorrent-1.0": "BitTorrent_1_0",
+    "BitTorrent-1.1": "BitTorrent_1_1",
+    "blessing": "Blessing",
+    "BlueOak-1.0.0": "BlueOak_1_0_0",
+    "Boehm-GC": "Boehm_GC",
+    "Borceux": "Borceux",
+    "Brian-Gladman-2-Clause": "Brian_Gladman_2_Clause",
+    "Brian-Gladman-3-Clause": "Brian_Gladman_3_Clause",
+    "BSD-1-Clause": "BSD_1_Clause",
+    "BSD-2-Clause": "BSD_2_Clause",
+    "BSD-2-Clause-Darwin": "BSD_2_Clause_Darwin",
+    "BSD-2-Clause-first-lines": "BSD_2_Clause_first_lines",
+    "BSD-2-Clause-Patent": "BSD_2_Clause_Patent",
+    "BSD-2-Clause-Views": "BSD_2_Clause_Views",
+    "BSD-3-Clause": "BSD_3_Clause",
+    "BSD-3-Clause-acpica": "BSD_3_Clause_acpica",
+    "BSD-3-Clause-Attribution": "BSD_3_Clause_Attribution",
+    "BSD-3-Clause-Clear": "BSD_3_Clause_Clear",
+    "BSD-3-Clause-flex": "BSD_3_Clause_flex",
+    "BSD-3-Clause-HP": "BSD_3_Clause_HP",
+    "BSD-3-Clause-LBNL": "BSD_3_Clause_LBNL",
+    "BSD-3-Clause-Modification": "BSD_3_Clause_Modification",
+    "BSD-3-Clause-No-Military-License": "BSD_3_Clause_No_Military_License",
+    "BSD-3-Clause-No-Nuclear-License": "BSD_3_Clause_No_Nuclear_License",
+    "BSD-3-Clause-No-Nuclear-License-2014": "BSD_3_Clause_No_Nuclear_License_2014",
+    "BSD-3-Clause-No-Nuclear-Warranty": "BSD_3_Clause_No_Nuclear_Warranty",
+    "BSD-3-Clause-Open-MPI": "BSD_3_Clause_Open_MPI",
+    "BSD-3-Clause-Sun": "BSD_3_Clause_Sun",
+    "BSD-4-Clause": "BSD_4_Clause",
+    "BSD-4-Clause-Shortened": "BSD_4_Clause_Shortened",
+    "BSD-4-Clause-UC": "BSD_4_Clause_UC",
+    "BSD-4.3RENO": "BSD_4_3RENO",
+    "BSD-4.3TAHOE": "BSD_4_3TAHOE",
+    "BSD-Advertising-Acknowledgement": "BSD_Advertising_Acknowledgement",
+    "BSD-Attribution-HPND-disclaimer": "BSD_Attribution_HPND_disclaimer",
+    "BSD-Inferno-Nettverk": "BSD_Inferno_Nettverk",
+    "BSD-Protection": "BSD_Protection",
+    "BSD-Source-beginning-file": "BSD_Source_beginning_file",
+    "BSD-Source-Code": "BSD_Source_Code",
+    "BSD-Systemics": "BSD_Systemics",
+    "BSD-Systemics-W3Works": "BSD_Systemics_W3Works",
+    "BSL-1.0": "BSL_1_0",
+    "BUSL-1.1": "BUSL_1_1",
+    "bzip2-1.0.6": "Bzip2_1_0_6",
+    "C-UDA-1.0": "C_UDA_1_0",
+    "CAL-1.0": "CAL_1_0",
+    "CAL-1.0-Combined-Work-Exception": "CAL_1_0_Combined_Work_Exception",
+    "Caldera": "Caldera",
+    "Caldera-no-preamble": "Caldera_no_preamble",
+    "Catharon": "Catharon",
+    "CATOSL-1.1": "CATOSL_1_1",
+    "CC-BY-1.0": "CC_BY_1_0",
+    "CC-BY-2.0": "CC_BY_2_0",
+    "CC-BY-2.5": "CC_BY_2_5",
+    "CC-BY-2.5-AU": "CC_BY_2_5_AU",
+    "CC-BY-3.0": "CC_BY_3_0",
+    "CC-BY-3.0-AT": "CC_BY_3_0_AT",
+    "CC-BY-3.0-AU": "CC_BY_3_0_AU",
+    "CC-BY-3.0-DE": "CC_BY_3_0_DE",
+    "CC-BY-3.0-IGO": "CC_BY_3_0_IGO",
+    "CC-BY-3.0-NL": "CC_BY_3_0_NL",
+    "CC-BY-3.0-US": "CC_BY_3_0_US",
+    "CC-BY-4.0": "CC_BY_4_0",
+    "CC-BY-NC-1.0": "CC_BY_NC_1_0",
+    "CC-BY-NC-2.0": "CC_BY_NC_2_0",
+    "CC-BY-NC-2.5": "CC_BY_NC_2_5",
+    "CC-BY-NC-3.0": "CC_BY_NC_3_0",
+    "CC-BY-NC-3.0-DE": "CC_BY_NC_3_0_DE",
+    "CC-BY-NC-4.0": "CC_BY_NC_4_0",
+    "CC-BY-NC-ND-1.0": "CC_BY_NC_ND_1_0",
+    "CC-BY-NC-ND-2.0": "CC_BY_NC_ND_2_0",
+    "CC-BY-NC-ND-2.5": "CC_BY_NC_ND_2_5",
+    "CC-BY-NC-ND-3.0": "CC_BY_NC_ND_3_0",
+    "CC-BY-NC-ND-3.0-DE": "CC_BY_NC_ND_3_0_DE",
+    "CC-BY-NC-ND-3.0-IGO": "CC_BY_NC_ND_3_0_IGO",
+    "CC-BY-NC-ND-4.0": "CC_BY_NC_ND_4_0",
+    "CC-BY-NC-SA-1.0": "CC_BY_NC_SA_1_0",
+    "CC-BY-NC-SA-2.0": "CC_BY_NC_SA_2_0",
+    "CC-BY-NC-SA-2.0-DE": "CC_BY_NC_SA_2_0_DE",
+    "CC-BY-NC-SA-2.0-FR": "CC_BY_NC_SA_2_0_FR",
+    "CC-BY-NC-SA-2.0-UK": "CC_BY_NC_SA_2_0_UK",
+    "CC-BY-NC-SA-2.5": "CC_BY_NC_SA_2_5",
+    "CC-BY-NC-SA-3.0": "CC_BY_NC_SA_3_0",
+    "CC-BY-NC-SA-3.0-DE": "CC_BY_NC_SA_3_0_DE",
+    "CC-BY-NC-SA-3.0-IGO": "CC_BY_NC_SA_3_0_IGO",
+    "CC-BY-NC-SA-4.0": "CC_BY_NC_SA_4_0",
+    "CC-BY-ND-1.0": "CC_BY_ND_1_0",
+    "CC-BY-ND-2.0": "CC_BY_ND_2_0",
+    "CC-BY-ND-2.5": "CC_BY_ND_2_5",
+    "CC-BY-ND-3.0": "CC_BY_ND_3_0",
+    "CC-BY-ND-3.0-DE": "CC_BY_ND_3_0_DE",
+    "CC-BY-ND-4.0": "CC_BY_ND_4_0",
+    "CC-BY-SA-1.0": "CC_BY_SA_1_0",
+    "CC-BY-SA-2.0": "CC_BY_SA_2_0",
+    "CC-BY-SA-2.0-UK": "CC_BY_SA_2_0_UK",
+    "CC-BY-SA-2.1-JP": "CC_BY_SA_2_1_JP",
+    "CC-BY-SA-2.5": "CC_BY_SA_2_5",
+    "CC-BY-SA-3.0": "CC_BY_SA_3_0",
+    "CC-BY-SA-3.0-AT": "CC_BY_SA_3_0_AT",
+    "CC-BY-SA-3.0-DE": "CC_BY_SA_3_0_DE",
+    "CC-BY-SA-3.0-IGO": "CC_BY_SA_3_0_IGO",
+    "CC-BY-SA-4.0": "CC_BY_SA_4_0",
+    "CC-PDDC": "CC_PDDC",
+    "CC0-1.0": "CC0_1_0",
+    "CDDL-1.0": "CDDL_1_0",
+    "CDDL-1.1": "CDDL_1_1",
+    "CDL-1.0": "CDL_1_0",
+    "CDLA-Permissive-1.0": "CDLA_Permissive_1_0",
+    "CDLA-Permissive-2.0": "CDLA_Permissive_2_0",
+    "CDLA-Sharing-1.0": "CDLA_Sharing_1_0",
+    "CECILL-1.0": "CECILL_1_0",
+    "CECILL-1.1": "CECILL_1_1",
+    "CECILL-2.0": "CECILL_2_0",
+    "CECILL-2.1": "CECILL_2_1",
+    "CECILL-B": "CECILL_B",
+    "CECILL-C": "CECILL_C",
+    "CERN-OHL-1.1": "CERN_OHL_1_1",
+    "CERN-OHL-1.2": "CERN_OHL_1_2",
+    "CERN-OHL-P-2.0": "CERN_OHL_P_2_0",
+    "CERN-OHL-S-2.0": "CERN_OHL_S_2_0",
+    "CERN-OHL-W-2.0": "CERN_OHL_W_2_0",
+    "CFITSIO": "CFITSIO",
+    "check-cvs": "Check_cvs",
+    "checkmk": "Checkmk",
+    "ClArtistic": "ClArtistic",
+    "Clips": "Clips",
+    "CMU-Mach": "CMU_Mach",
+    "CMU-Mach-nodoc": "CMU_Mach_nodoc",
+    "CNRI-Jython": "CNRI_Jython",
+    "CNRI-Python": "CNRI_Python",
+    "CNRI-Python-GPL-Compatible": "CNRI_Python_GPL_Compatible",
+    "COIL-1.0": "COIL_1_0",
+    "Community-Spec-1.0": "Community_Spec_1_0",
+    "Condor-1.1": "Condor_1_1",
+    "copyleft-next-0.3.0": "Copyleft_next_0_3_0",
+    "copyleft-next-0.3.1": "Copyleft_next_0_3_1",
+    "Cornell-Lossless-JPEG": "Cornell_Lossless_JPEG",
+    "CPAL-1.0": "CPAL_1_0",
+    "CPL-1.0": "CPL_1_0",
+    "CPOL-1.02": "CPOL_1_02",
+    "Cronyx": "Cronyx",
+    "Crossword": "Crossword",
+    "CrystalStacker": "CrystalStacker",
+    "CUA-OPL-1.0": "CUA_OPL_1_0",
+    "Cube": "Cube",
+    "curl": "Curl",
+    "cve-tou": "Cve_tou",
+    "D-FSL-1.0": "D_FSL_1_0",
+    "DEC-3-Clause": "DEC_3_Clause",
+    "diffmark": "Diffmark",
+    "DL-DE-BY-2.0": "DL_DE_BY_2_0",
+    "DL-DE-ZERO-2.0": "DL_DE_ZERO_2_0",
+    "DOC": "Doc",
+    "Dotseqn": "Dotseqn",
+    "DRL-1.0": "DRL_1_0",
+    "DRL-1.1": "DRL_1_1",
+    "DSDP": "DSDP",
+    "dtoa": "Dtoa",
+    "dvipdfm": "Dvipdfm",
+    "ECL-1.0": "ECL_1_0",
+    "ECL-2.0": "ECL_2_0",
+    "EFL-1.0": "EFL_1_0",
+    "EFL-2.0": "EFL_2_0",
+    "eGenix": "EGenix",
+    "Elastic-2.0": "Elastic_2_0",
+    "Entessa": "Entessa",
+    "EPICS": "EPICS",
+    "EPL-1.0": "EPL_1_0",
+    "EPL-2.0": "EPL_2_0",
+    "ErlPL-1.1": "ErlPL_1_1",
+    "etalab-2.0": "Etalab_2_0",
+    "EUDatagrid": "EUDatagrid",
+    "EUPL-1.0": "EUPL_1_0",
+    "EUPL-1.1": "EUPL_1_1",
+    "EUPL-1.2": "EUPL_1_2",
+    "Eurosym": "Eurosym",
+    "Fair": "Fair",
+    "FBM": "FBM",
+    "FDK-AAC": "FDK_AAC",
+    "Ferguson-Twofish": "Ferguson_Twofish",
+    "Frameworx-1.0": "Frameworx_1_0",
+    "FreeBSD-DOC": "FreeBSD_DOC",
+    "FreeImage": "FreeImage",
+    "FSFAP": "FSFAP",
+    "FSFAP-no-warranty-disclaimer": "FSFAP_no_warranty_disclaimer",
+    "FSFUL": "FSFUL",
+    "FSFULLR": "FSFULLR",
+    "FSFULLRWD": "FSFULLRWD",
+    "FTL": "FTL",
+    "Furuseth": "Furuseth",
+    "fwlw": "Fwlw",
+    "GCR-docs": "GCR_docs",
+    "GD": "GD",
+    "GFDL-1.1-invariants-only": "GFDL_1_1_invariants_only",
+    "GFDL-1.1-invariants-or-later": "GFDL_1_1_invariants_or_later",
+    "GFDL-1.1-no-invariants-only": "GFDL_1_1_no_invariants_only",
+    "GFDL-1.1-no-invariants-or-later": "GFDL_1_1_no_invariants_or_later",
+    "GFDL-1.1-only": "GFDL_1_1_only",
+    "GFDL-1.1-or-later": "GFDL_1_1_or_later",
+    "GFDL-1.2-invariants-only": "GFDL_1_2_invariants_only",
+    "GFDL-1.2-invariants-or-later": "GFDL_1_2_invariants_or_later",
+    "GFDL-1.2-no-invariants-only": "GFDL_1_2_no_invariants_only",
+    "GFDL-1.2-no-invariants-or-later": "GFDL_1_2_no_invariants_or_later",
+    "GFDL-1.2-only": "GFDL_1_2_only",
+    "GFDL-1.2-or-later": "GFDL_1_2_or_later",
+    "GFDL-1.3-invariants-only": "GFDL_1_3_invariants_only",
+    "GFDL-1.3-invariants-or-later": "GFDL_1_3_invariants_or_later",
+    "GFDL-1.3-no-invariants-only": "GFDL_1_3_no_invariants_only",
+    "GFDL-1.3-no-invariants-or-later": "GFDL_1_3_no_invariants_or_later",
+    "GFDL-1.3-only": "GFDL_1_3_only",
+    "GFDL-1.3-or-later": "GFDL_1_3_or_later",
+    "Giftware": "Giftware",
+    "GL2PS": "GL2PS",
+    "Glide": "Glide",
+    "Glulxe": "Glulxe",
+    "GLWTPL": "GLWTPL",
+    "gnuplot": "Gnuplot",
+    "GPL-1.0-only": "GPL_1_0_only",
+    "GPL-1.0-or-later": "GPL_1_0_or_later",
+    "GPL-2.0-only": "GPL_2_0_only",
+    "GPL-2.0-or-later": "GPL_2_0_or_later",
+    "GPL-3.0-only": "GPL_3_0_only",
+    "GPL-3.0-or-later": "GPL_3_0_or_later",
+    "Graphics-Gems": "Graphics_Gems",
+    "gSOAP-1.3b": "GSOAP_1_3b",
+    "gtkbook": "Gtkbook",
+    "Gutmann": "Gutmann",
+    "HaskellReport": "HaskellReport",
+    "hdparm": "Hdparm",
+    "Hippocratic-2.1": "Hippocratic_2_1",
+    "HP-1986": "HP_1986",
+    "HP-1989": "HP_1989",
+    "HPND": "HPND",
+    "HPND-DEC": "HPND_DEC",
+    "HPND-doc": "HPND_doc",
+    "HPND-doc-sell": "HPND_doc_sell",
+    "HPND-export-US": "HPND_export_US",
+    "HPND-export-US-acknowledgement": "HPND_export_US_acknowledgement",
+    "HPND-export-US-modify": "HPND_export_US_modify",
+    "HPND-export2-US": "HPND_export2_US",
+    "HPND-Fenneberg-Livingston": "HPND_Fenneberg_Livingston",
+    "HPND-INRIA-IMAG": "HPND_INRIA_IMAG",
+    "HPND-Intel": "HPND_Intel",
+    "HPND-Kevlin-Henney": "HPND_Kevlin_Henney",
+    "HPND-Markus-Kuhn": "HPND_Markus_Kuhn",
+    "HPND-merchantability-variant": "HPND_merchantability_variant",
+    "HPND-MIT-disclaimer": "HPND_MIT_disclaimer",
+    "HPND-Pbmplus": "HPND_Pbmplus",
+    "HPND-sell-MIT-disclaimer-xserver": "HPND_sell_MIT_disclaimer_xserver",
+    "HPND-sell-regexpr": "HPND_sell_regexpr",
+    "HPND-sell-variant": "HPND_sell_variant",
+    "HPND-sell-variant-MIT-disclaimer": "HPND_sell_variant_MIT_disclaimer",
+    "HPND-sell-variant-MIT-disclaimer-rev": "HPND_sell_variant_MIT_disclaimer_rev",
+    "HPND-UC": "HPND_UC",
+    "HPND-UC-export-US": "HPND_UC_export_US",
+    "HTMLTIDY": "HTMLTIDY",
+    "IBM-pibs": "IBM_pibs",
+    "ICU": "ICU",
+    "IEC-Code-Components-EULA": "IEC_Code_Components_EULA",
+    "IJG": "IJG",
+    "IJG-short": "IJG_short",
+    "ImageMagick": "ImageMagick",
+    "iMatix": "IMatix",
+    "Imlib2": "Imlib2",
+    "Info-ZIP": "Info_ZIP",
+    "Inner-Net-2.0": "Inner_Net_2_0",
+    "Intel": "Intel",
+    "Intel-ACPI": "Intel_ACPI",
+    "Interbase-1.0": "Interbase_1_0",
+    "IPA": "IPA",
+    "IPL-1.0": "IPL_1_0",
+    "ISC": "ISC",
+    "ISC-Veillard": "ISC_Veillard",
+    "Jam": "Jam",
+    "JasPer-2.0": "JasPer_2_0",
+    "JPL-image": "JPL_image",
+    "JPNIC": "JPNIC",
+    "JSON": "JSON",
+    "Kastrup": "Kastrup",
+    "Kazlib": "Kazlib",
+    "Knuth-CTAN": "Knuth_CTAN",
+    "LAL-1.2": "LAL_1_2",
+    "LAL-1.3": "LAL_1_3",
+    "Latex2e": "Latex2e",
+    "Latex2e-translated-notice": "Latex2e_translated_notice",
+    "Leptonica": "Leptonica",
+    "LGPL-2.0-only": "LGPL_2_0_only",
+    "LGPL-2.0-or-later": "LGPL_2_0_or_later",
+    "LGPL-2.1-only": "LGPL_2_1_only",
+    "LGPL-2.1-or-later": "LGPL_2_1_or_later",
+    "LGPL-3.0-only": "LGPL_3_0_only",
+    "LGPL-3.0-or-later": "LGPL_3_0_or_later",
+    "LGPLLR": "LGPLLR",
+    "Libpng": "Libpng",
+    "libpng-2.0": "Libpng_2_0",
+    "libselinux-1.0": "Libselinux_1_0",
+    "libtiff": "Libtiff",
+    "libutil-David-Nugent": "Libutil_David_Nugent",
+    "LiLiQ-P-1.1": "LiLiQ_P_1_1",
+    "LiLiQ-R-1.1": "LiLiQ_R_1_1",
+    "LiLiQ-Rplus-1.1": "LiLiQ_Rplus_1_1",
+    "Linux-man-pages-1-para": "Linux_man_pages_1_para",
+    "Linux-man-pages-copyleft": "Linux_man_pages_copyleft",
+    "Linux-man-pages-copyleft-2-para": "Linux_man_pages_copyleft_2_para",
+    "Linux-man-pages-copyleft-var": "Linux_man_pages_copyleft_var",
+    "Linux-OpenIB": "Linux_OpenIB",
+    "LOOP": "LOOP",
+    "LPD-document": "LPD_document",
+    "LPL-1.0": "LPL_1_0",
+    "LPL-1.02": "LPL_1_02",
+    "LPPL-1.0": "LPPL_1_0",
+    "LPPL-1.1": "LPPL_1_1",
+    "LPPL-1.2": "LPPL_1_2",
+    "LPPL-1.3a": "LPPL_1_3a",
+    "LPPL-1.3c": "LPPL_1_3c",
+    "lsof": "Lsof",
+    "Lucida-Bitmap-Fonts": "Lucida_Bitmap_Fonts",
+    "LZMA-SDK-9.11-to-9.20": "LZMA_SDK_9_11_to_9_20",
+    "LZMA-SDK-9.22": "LZMA_SDK_9_22",
+    "Mackerras-3-Clause": "Mackerras_3_Clause",
+    "Mackerras-3-Clause-acknowledgment": "Mackerras_3_Clause_acknowledgment",
+    "magaz": "Magaz",
+    "mailprio": "Mailprio",
+    "MakeIndex": "MakeIndex",
+    "Martin-Birgmeier": "Martin_Birgmeier",
+    "McPhee-slideshow": "McPhee_slideshow",
+    "metamail": "Metamail",
+    "Minpack": "Minpack",
+    "MirOS": "MirOS",
+    "MIT": "MIT",
+    "MIT-0": "MIT_0",
+    "MIT-advertising": "MIT_advertising",
+    "MIT-CMU": "MIT_CMU",
+    "MIT-enna": "MIT_enna",
+    "MIT-feh": "MIT_feh",
+    "MIT-Festival": "MIT_Festival",
+    "MIT-Khronos-old": "MIT_Khronos_old",
+    "MIT-Modern-Variant": "MIT_Modern_Variant",
+    "MIT-open-group": "MIT_open_group",
+    "MIT-testregex": "MIT_testregex",
+    "MIT-Wu": "MIT_Wu",
+    "MITNFA": "MITNFA",
+    "MMIXware": "MMIXware",
+    "Motosoto": "Motosoto",
+    "MPEG-SSG": "MPEG_SSG",
+    "mpi-permissive": "Mpi_permissive",
+    "mpich2": "Mpich2",
+    "MPL-1.0": "MPL_1_0",
+    "MPL-1.1": "MPL_1_1",
+    "MPL-2.0": "MPL_2_0",
+    "MPL-2.0-no-copyleft-exception": "MPL_2_0_no_copyleft_exception",
+    "mplus": "Mplus",
+    "MS-LPL": "MS_LPL",
+    "MS-PL": "MS_PL",
+    "MS-RL": "MS_RL",
+    "MTLL": "MTLL",
+    "MulanPSL-1.0": "MulanPSL_1_0",
+    "MulanPSL-2.0": "MulanPSL_2_0",
+    "Multics": "Multics",
+    "Mup": "Mup",
+    "NAIST-2003": "NAIST_2003",
+    "NASA-1.3": "NASA_1_3",
+    "Naumen": "Naumen",
+    "NBPL-1.0": "NBPL_1_0",
+    "NCBI-PD": "NCBI_PD",
+    "NCGL-UK-2.0": "NCGL_UK_2_0",
+    "NCL": "NCL",
+    "NCSA": "NCSA",
+    "Net-SNMP": "Net_SNMP",
+    "NetCDF": "NetCDF",
+    "Newsletr": "Newsletr",
+    "NGPL": "NGPL",
+    "NICTA-1.0": "NICTA_1_0",
+    "NIST-PD": "NIST_PD",
+    "NIST-PD-fallback": "NIST_PD_fallback",
+    "NIST-Software": "NIST_Software",
+    "NLOD-1.0": "NLOD_1_0",
+    "NLOD-2.0": "NLOD_2_0",
+    "NLPL": "NLPL",
+    "Nokia": "Nokia",
+    "NOSL": "NOSL",
+    "Noweb": "Noweb",
+    "NPL-1.0": "NPL_1_0",
+    "NPL-1.1": "NPL_1_1",
+    "NPOSL-3.0": "NPOSL_3_0",
+    "NRL": "NRL",
+    "NTP": "NTP",
+    "NTP-0": "NTP_0",
+    "O-UDA-1.0": "O_UDA_1_0",
+    "OAR": "OAR",
+    "OCCT-PL": "OCCT_PL",
+    "OCLC-2.0": "OCLC_2_0",
+    "ODbL-1.0": "ODbL_1_0",
+    "ODC-By-1.0": "ODC_By_1_0",
+    "OFFIS": "OFFIS",
+    "OFL-1.0": "OFL_1_0",
+    "OFL-1.0-no-RFN": "OFL_1_0_no_RFN",
+    "OFL-1.0-RFN": "OFL_1_0_RFN",
+    "OFL-1.1": "OFL_1_1",
+    "OFL-1.1-no-RFN": "OFL_1_1_no_RFN",
+    "OFL-1.1-RFN": "OFL_1_1_RFN",
+    "OGC-1.0": "OGC_1_0",
+    "OGDL-Taiwan-1.0": "OGDL_Taiwan_1_0",
+    "OGL-Canada-2.0": "OGL_Canada_2_0",
+    "OGL-UK-1.0": "OGL_UK_1_0",
+    "OGL-UK-2.0": "OGL_UK_2_0",
+    "OGL-UK-3.0": "OGL_UK_3_0",
+    "OGTSL": "OGTSL",
+    "OLDAP-1.1": "OLDAP_1_1",
+    "OLDAP-1.2": "OLDAP_1_2",
+    "OLDAP-1.3": "OLDAP_1_3",
+    "OLDAP-1.4": "OLDAP_1_4",
+    "OLDAP-2.0": "OLDAP_2_0",
+    "OLDAP-2.0.1": "OLDAP_2_0_1",
+    "OLDAP-2.1": "OLDAP_2_1",
+    "OLDAP-2.2": "OLDAP_2_2",
+    "OLDAP-2.2.1": "OLDAP_2_2_1",
+    "OLDAP-2.2.2": "OLDAP_2_2_2",
+    "OLDAP-2.3": "OLDAP_2_3",
+    "OLDAP-2.4": "OLDAP_2_4",
+    "OLDAP-2.5": "OLDAP_2_5",
+    "OLDAP-2.6": "OLDAP_2_6",
+    "OLDAP-2.7": "OLDAP_2_7",
+    "OLDAP-2.8": "OLDAP_2_8",
+    "OLFL-1.3": "OLFL_1_3",
+    "OML": "OML",
+    "OpenPBS-2.3": "OpenPBS_2_3",
+    "OpenSSL": "OpenSSL",
+    "OpenSSL-standalone": "OpenSSL_standalone",
+    "OpenVision": "OpenVision",
+    "OPL-1.0": "OPL_1_0",
+    "OPL-UK-3.0": "OPL_UK_3_0",
+    "OPUBL-1.0": "OPUBL_1_0",
+    "OSET-PL-2.1": "OSET_PL_2_1",
+    "OSL-1.0": "OSL_1_0",
+    "OSL-1.1": "OSL_1_1",
+    "OSL-2.0": "OSL_2_0",
+    "OSL-2.1": "OSL_2_1",
+    "OSL-3.0": "OSL_3_0",
+    "PADL": "PADL",
+    "Parity-6.0.0": "Parity_6_0_0",
+    "Parity-7.0.0": "Parity_7_0_0",
+    "PDDL-1.0": "PDDL_1_0",
+    "PHP-3.0": "PHP_3_0",
+    "PHP-3.01": "PHP_3_01",
+    "Pixar": "Pixar",
+    "pkgconf": "Pkgconf",
+    "Plexus": "Plexus",
+    "pnmstitch": "Pnmstitch",
+    "PolyForm-Noncommercial-1.0.0": "PolyForm_Noncommercial_1_0_0",
+    "PolyForm-Small-Business-1.0.0": "PolyForm_Small_Business_1_0_0",
+    "PostgreSQL": "PostgreSQL",
+    "PPL": "PPL",
+    "PSF-2.0": "PSF_2_0",
+    "psfrag": "Psfrag",
+    "psutils": "Psutils",
+    "Python-2.0": "Python_2_0",
+    "Python-2.0.1": "Python_2_0_1",
+    "python-ldap": "Python_ldap",
+    "Qhull": "Qhull",
+    "QPL-1.0": "QPL_1_0",
+    "QPL-1.0-INRIA-2004": "QPL_1_0_INRIA_2004",
+    "radvd": "Radvd",
+    "Rdisc": "Rdisc",
+    "RHeCos-1.1": "RHeCos_1_1",
+    "RPL-1.1": "RPL_1_1",
+    "RPL-1.5": "RPL_1_5",
+    "RPSL-1.0": "RPSL_1_0",
+    "RSA-MD": "RSA_MD",
+    "RSCPL": "RSCPL",
+    "Ruby": "Ruby",
+    "SAX-PD": "SAX_PD",
+    "SAX-PD-2.0": "SAX_PD_2_0",
+    "Saxpath": "Saxpath",
+    "SCEA": "SCEA",
+    "SchemeReport": "SchemeReport",
+    "Sendmail": "Sendmail",
+    "Sendmail-8.23": "Sendmail_8_23",
+    "SGI-B-1.0": "SGI_B_1_0",
+    "SGI-B-1.1": "SGI_B_1_1",
+    "SGI-B-2.0": "SGI_B_2_0",
+    "SGI-OpenGL": "SGI_OpenGL",
+    "SGP4": "SGP4",
+    "SHL-0.5": "SHL_0_5",
+    "SHL-0.51": "SHL_0_51",
+    "SimPL-2.0": "SimPL_2_0",
+    "SISSL": "SISSL",
+    "SISSL-1.2": "SISSL_1_2",
+    "SL": "SL",
+    "Sleepycat": "Sleepycat",
+    "SMLNJ": "SMLNJ",
+    "SMPPL": "SMPPL",
+    "SNIA": "SNIA",
+    "snprintf": "Snprintf",
+    "softSurfer": "SoftSurfer",
+    "Soundex": "Soundex",
+    "Spencer-86": "Spencer_86",
+    "Spencer-94": "Spencer_94",
+    "Spencer-99": "Spencer_99",
+    "SPL-1.0": "SPL_1_0",
+    "ssh-keyscan": "Ssh_keyscan",
+    "SSH-OpenSSH": "SSH_OpenSSH",
+    "SSH-short": "SSH_short",
+    "SSLeay-standalone": "SSLeay_standalone",
+    "SSPL-1.0": "SSPL_1_0",
+    "SugarCRM-1.1.3": "SugarCRM_1_1_3",
+    "Sun-PPP": "Sun_PPP",
+    "Sun-PPP-2000": "Sun_PPP_2000",
+    "SunPro": "SunPro",
+    "SWL": "SWL",
+    "swrule": "Swrule",
+    "Symlinks": "Symlinks",
+    "TAPR-OHL-1.0": "TAPR_OHL_1_0",
+    "TCL": "TCL",
+    "TCP-wrappers": "TCP_wrappers",
+    "TermReadKey": "TermReadKey",
+    "TGPPL-1.0": "TGPPL_1_0",
+    "threeparttable": "Threeparttable",
+    "TMate": "TMate",
+    "TORQUE-1.1": "TORQUE_1_1",
+    "TOSL": "TOSL",
+    "TPDL": "TPDL",
+    "TPL-1.0": "TPL_1_0",
+    "TTWL": "TTWL",
+    "TTYP0": "TTYP0",
+    "TU-Berlin-1.0": "TU_Berlin_1_0",
+    "TU-Berlin-2.0": "TU_Berlin_2_0",
+    "UCAR": "UCAR",
+    "UCL-1.0": "UCL_1_0",
+    "ulem": "Ulem",
+    "UMich-Merit": "UMich_Merit",
+    "Unicode-3.0": "Unicode_3_0",
+    "Unicode-DFS-2015": "Unicode_DFS_2015",
+    "Unicode-DFS-2016": "Unicode_DFS_2016",
+    "Unicode-TOU": "Unicode_TOU",
+    "UnixCrypt": "UnixCrypt",
+    "Unlicense": "Unlicense",
+    "UPL-1.0": "UPL_1_0",
+    "URT-RLE": "URT_RLE",
+    "Vim": "Vim",
+    "VOSTROM": "VOSTROM",
+    "VSL-1.0": "VSL_1_0",
+    "W3C": "W3C",
+    "W3C-19980720": "W3C_19980720",
+    "W3C-20150513": "W3C_20150513",
+    "w3m": "W3m",
+    "Watcom-1.0": "Watcom_1_0",
+    "Widget-Workshop": "Widget_Workshop",
+    "Wsuipa": "Wsuipa",
+    "WTFPL": "WTFPL",
+    "X11": "X11",
+    "X11-distribute-modifications-variant": "X11_distribute_modifications_variant",
+    "Xdebug-1.03": "Xdebug_1_03",
+    "Xerox": "Xerox",
+    "Xfig": "Xfig",
+    "XFree86-1.1": "XFree86_1_1",
+    "xinetd": "Xinetd",
+    "xkeyboard-config-Zinoviev": "Xkeyboard_Config_Zinoviev",
+    "xlock": "Xlock",
+    "Xnet": "Xnet",
+    "xpp": "Xpp",
+    "XSkat": "XSkat",
+    "xzoom": "Xzoom",
+    "YPL-1.0": "YPL_1_0",
+    "YPL-1.1": "YPL_1_1",
+    "Zed": "Zed",
+    "Zeeff": "Zeeff",
+    "Zend-2.0": "Zend_2_0",
+    "Zimbra-1.3": "Zimbra_1_3",
+    "Zimbra-1.4": "Zimbra_1_4",
+    "Zlib": "Zlib",
+    "zlib-acknowledgement": "Zlib_acknowledgement",
+    "ZPL-1.1": "ZPL_1_1",
+    "ZPL-2.0": "ZPL_2_0",
+    "ZPL-2.1": "ZPL_2_1"
+}
diff --git a/src/Web/ArchLinux/Internal/KnownSPDXLoader.hs b/src/Web/ArchLinux/Internal/KnownSPDXLoader.hs
new file mode 100644
--- /dev/null
+++ b/src/Web/ArchLinux/Internal/KnownSPDXLoader.hs
@@ -0,0 +1,45 @@
+{-# LANGUAGE TemplateHaskellQuotes #-}
+
+module Web.ArchLinux.Internal.KnownSPDXLoader (loadKnownSPDX) where
+
+import Data.Aeson
+import qualified Data.ByteString as BS
+import Data.Map.Strict (Map, toList)
+import GHC.Generics (Generic)
+import Language.Haskell.TH
+import System.Directory (getCurrentDirectory)
+import System.FilePath ((</>))
+
+-- | Load the KNOWN_SPDX.json file at compile time and generate data type 'License', and
+-- functions 'parseLicense' and 'licenseId'. If the license string is not known, 'parseLicense'
+-- will return 'Custom' with the original string, and 'licenseId' will return the original string
+-- for 'Custom' licenses.
+loadKnownSPDX :: DecsQ
+loadKnownSPDX = do
+  txt <- runIO $ getCurrentDirectory >>= \dot -> BS.readFile $ dot </> "data" </> "KNOWN_SPDX.json"
+  let (toList -> src) = case decodeStrict @(Map String String) txt of
+        Just x -> x
+        _ -> error "Failed to parse json"
+  dec1 <- genData src
+  dec2 <- genParse src
+  dec3 <- genId src
+  pure [dec1, dec2, dec3]
+
+genData :: [(String, String)] -> DecQ
+genData src = dataD_doc (pure []) (mkName "License") [] Nothing (customCon : (genCon <$> src)) drv (pure "SPDX License Identifiers included in @/usr/share/licenses/known_spdx_license_identifiers.txt@ of package <https://archlinux.org/packages/core/any/licenses/>.")
+  where
+    customCon = (normalC (mkName "Custom") [bangType (bang (pure NoSourceUnpackedness) (pure NoSourceStrictness)) [t|String|]], Nothing, [])
+    genCon (from, to) = (normalC (mkName to) [], pure $ unwords ["@", from, "@"], [])
+    drv = [derivClause (pure StockStrategy) [[t|Show|], [t|Eq|], [t|Ord|], [t|Generic|]]]
+
+genParse :: [(String, String)] -> DecQ
+genParse src = funD_doc (mkName "parseLicense") ((genClause <$> src) <> [custom]) (pure "Parse a SPDX license identifier. If the identifier is not known, return 'Custom' with the original string.") []
+  where
+    custom = clause [varP (mkName "s")] (normalB [|Custom s|]) []
+    genClause (from, to) = clause [litP (StringL from)] (normalB $ conE (mkName to)) []
+
+genId :: [(String, String)] -> DecQ
+genId src = funD_doc (mkName "licenseId") ((genClause <$> src) <> [custom]) (pure "Get the SPDX license identifier. If the license is 'Custom', return the original string.") []
+  where
+    custom = clause [conP (mkName "Custom") [varP (mkName "s")]] (normalB [|s|]) []
+    genClause (from, to) = clause [conP (mkName to) []] (normalB $ litE (StringL from)) []
diff --git a/src/Web/ArchLinux/Types.hs b/src/Web/ArchLinux/Types.hs
--- a/src/Web/ArchLinux/Types.hs
+++ b/src/Web/ArchLinux/Types.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE DuplicateRecordFields #-}
 {-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE TemplateHaskell #-}
 
 -- | Copyright: (c) 2021 berberman
 -- SPDX-License-Identifier: MIT
@@ -38,6 +39,7 @@
 import Data.Time (UTCTime)
 import Deriving.Aeson
 import Servant.API (ToHttpApiData (..))
+import Web.ArchLinux.Internal.KnownSPDXLoader
 
 type ArchLinuxJSON = CustomJSON '[FieldLabelModifier (StripPrefix "_", CamelToSnake)]
 
@@ -96,316 +98,16 @@
 instance ToHttpApiData Arch where
   toQueryParam = toQueryParamViaJSON
 
--- | SPDX License Identifiers included in <https://archlinux.org/packages/core/any/licenses/>,
-data License
-  = AGPL_3_0_only
-  | AGPL_3_0_or_later
-  | Apache_2_0
-  | Artistic_1_0_Perl
-  | Artistic_2_0
-  | BSL_1_0
-  | CC_BY_1_0
-  | CC_BY_2_0
-  | CC_BY_2_5
-  | CC_BY_3_0_AT
-  | CC_BY_3_0_US
-  | CC_BY_3_0
-  | CC_BY_4_0
-  | CC_BY_NC_1_0
-  | CC_BY_NC_2_0
-  | CC_BY_NC_2_5
-  | CC_BY_NC_3_0
-  | CC_BY_NC_4_0
-  | CC_BY_NC_ND_1_0
-  | CC_BY_NC_ND_2_0
-  | CC_BY_NC_ND_2_5
-  | CC_BY_NC_ND_3_0_IGO
-  | CC_BY_NC_ND_3_0
-  | CC_BY_NC_ND_4_0
-  | CC_BY_NC_SA_1_0
-  | CC_BY_NC_SA_2_0
-  | CC_BY_NC_SA_2_5
-  | CC_BY_NC_SA_3_0
-  | CC_BY_NC_SA_4_0
-  | CC_BY_ND_1_0
-  | CC_BY_ND_2_0
-  | CC_BY_ND_2_5
-  | CC_BY_ND_3_0
-  | CC_BY_ND_4_0
-  | CC_BY_SA_1_0
-  | CC_BY_SA_2_0_UK
-  | CC_BY_SA_2_1_JP
-  | CC_BY_SA_2_5
-  | CC_BY_SA_3_0_AT
-  | CC_BY_SA_3_0
-  | CC_BY_SA_4_0
-  | CC_PDDC
-  | CC0_1_0
-  | CDDL_1_0
-  | CDDL_1_1
-  | CPL_1_0
-  | EPL_1_0
-  | EPL_2_0
-  | FSFAP
-  | GFDL_1_1_invariants_only
-  | GFDL_1_1_invariants_or_later
-  | GFDL_1_1_no_invariants_only
-  | GFDL_1_1_no_invariants_or_later
-  | GFDL_1_1_only
-  | GFDL_1_1_or_later
-  | GFDL_1_2_invariants_only
-  | GFDL_1_2_invariants_or_later
-  | GFDL_1_2_no_invariants_only
-  | GFDL_1_2_no_invariants_or_later
-  | GFDL_1_2_only
-  | GFDL_1_2_or_later
-  | GFDL_1_3_invariants_only
-  | GFDL_1_3_invariants_or_later
-  | GFDL_1_3_no_invariants_only
-  | GFDL_1_3_no_invariants_or_later
-  | GFDL_1_3_only
-  | GFDL_1_3_or_later
-  | GPL_1_0_only
-  | GPL_1_0_or_later
-  | GPL_2_0_only
-  | GPL_2_0_or_later
-  | GPL_3_0_only
-  | GPL_3_0_or_later
-  | LGPL_2_0_only
-  | LGPL_2_0_or_later
-  | LGPL_2_1_only
-  | LGPL_2_1_or_later
-  | LGPL_3_0_only
-  | LGPL_3_0_or_later
-  | LGPLLR
-  | LPPL_1_0
-  | LPPL_1_1
-  | LPPL_1_2
-  | LPPL_1_3a
-  | LPPL_1_3c
-  | MPL_1_0
-  | MPL_1_1
-  | MPL_2_0
-  | PHP_3_0
-  | PHP_3_01
-  | PSF_2_0
-  | Ruby
-  | Unlicense
-  | W3C
-  | WTFPL
-  | ZPL_1_1
-  | ZPL_2_0
-  | ZPL_2_1
-  | Custom Text
-  deriving stock (Show, Eq, Ord, Generic)
-
-licenseId :: License -> Text
-licenseId AGPL_3_0_only = "AGPL-3.0-only"
-licenseId AGPL_3_0_or_later = "AGPL-3.0-or-later"
-licenseId Apache_2_0 = "Apache-2.0"
-licenseId Artistic_1_0_Perl = "Artistic-1.0-Perl"
-licenseId Artistic_2_0 = "Artistic-2.0"
-licenseId BSL_1_0 = "BSL-1.0"
-licenseId CC_BY_1_0 = "CC-BY-1.0"
-licenseId CC_BY_2_0 = "CC-BY-2.0"
-licenseId CC_BY_2_5 = "CC-BY-2.5"
-licenseId CC_BY_3_0_AT = "CC-BY-3.0-AT"
-licenseId CC_BY_3_0_US = "CC-BY-3.0-US"
-licenseId CC_BY_3_0 = "CC-BY-3.0"
-licenseId CC_BY_4_0 = "CC-BY-4.0"
-licenseId CC_BY_NC_1_0 = "CC-BY-NC-1.0"
-licenseId CC_BY_NC_2_0 = "CC-BY-NC-2.0"
-licenseId CC_BY_NC_2_5 = "CC-BY-NC-2.5"
-licenseId CC_BY_NC_3_0 = "CC-BY-NC-3.0"
-licenseId CC_BY_NC_4_0 = "CC-BY-NC-4.0"
-licenseId CC_BY_NC_ND_1_0 = "CC-BY-NC-ND-1.0"
-licenseId CC_BY_NC_ND_2_0 = "CC-BY-NC-ND-2.0"
-licenseId CC_BY_NC_ND_2_5 = "CC-BY-NC-ND-2.5"
-licenseId CC_BY_NC_ND_3_0_IGO = "CC-BY-NC-ND-3.0-IGO"
-licenseId CC_BY_NC_ND_3_0 = "CC-BY-NC-ND-3.0"
-licenseId CC_BY_NC_ND_4_0 = "CC-BY-NC-ND-4.0"
-licenseId CC_BY_NC_SA_1_0 = "CC-BY-NC-SA-1.0"
-licenseId CC_BY_NC_SA_2_0 = "CC-BY-NC-SA-2.0"
-licenseId CC_BY_NC_SA_2_5 = "CC-BY-NC-SA-2.5"
-licenseId CC_BY_NC_SA_3_0 = "CC-BY-NC-SA-3.0"
-licenseId CC_BY_NC_SA_4_0 = "CC-BY-NC-SA-4.0"
-licenseId CC_BY_ND_1_0 = "CC-BY-ND-1.0"
-licenseId CC_BY_ND_2_0 = "CC-BY-ND-2.0"
-licenseId CC_BY_ND_2_5 = "CC-BY-ND-2.5"
-licenseId CC_BY_ND_3_0 = "CC-BY-ND-3.0"
-licenseId CC_BY_ND_4_0 = "CC-BY-ND-4.0"
-licenseId CC_BY_SA_1_0 = "CC-BY-SA-1.0"
-licenseId CC_BY_SA_2_0_UK = "CC-BY-SA-2.0-UK"
-licenseId CC_BY_SA_2_1_JP = "CC-BY-SA-2.1-JP"
-licenseId CC_BY_SA_2_5 = "CC-BY-SA-2.5"
-licenseId CC_BY_SA_3_0_AT = "CC-BY-SA-3.0-AT"
-licenseId CC_BY_SA_3_0 = "CC-BY-SA-3.0"
-licenseId CC_BY_SA_4_0 = "CC-BY-SA-4.0"
-licenseId CC_PDDC = "CC-PDDC"
-licenseId CC0_1_0 = "CC0-1.0"
-licenseId CDDL_1_0 = "CDDL-1.0"
-licenseId CDDL_1_1 = "CDDL-1.1"
-licenseId CPL_1_0 = "CPL-1.0"
-licenseId EPL_1_0 = "EPL-1.0"
-licenseId EPL_2_0 = "EPL-2.0"
-licenseId FSFAP = "FSFAP"
-licenseId GFDL_1_1_invariants_only = "GFDL-1.1-invariants-only"
-licenseId GFDL_1_1_invariants_or_later = "GFDL-1.1-invariants-or-later"
-licenseId GFDL_1_1_no_invariants_only = "GFDL-1.1-no-invariants-only"
-licenseId GFDL_1_1_no_invariants_or_later = "GFDL-1.1-no-invariants-or-later"
-licenseId GFDL_1_1_only = "GFDL-1.1-only"
-licenseId GFDL_1_1_or_later = "GFDL-1.1-or-later"
-licenseId GFDL_1_2_invariants_only = "GFDL-1.2-invariants-only"
-licenseId GFDL_1_2_invariants_or_later = "GFDL-1.2-invariants-or-later"
-licenseId GFDL_1_2_no_invariants_only = "GFDL-1.2-no-invariants-only"
-licenseId GFDL_1_2_no_invariants_or_later = "GFDL-1.2-no-invariants-or-later"
-licenseId GFDL_1_2_only = "GFDL-1.2-only"
-licenseId GFDL_1_2_or_later = "GFDL-1.2-or-later"
-licenseId GFDL_1_3_invariants_only = "GFDL-1.3-invariants-only"
-licenseId GFDL_1_3_invariants_or_later = "GFDL-1.3-invariants-or-later"
-licenseId GFDL_1_3_no_invariants_only = "GFDL-1.3-no-invariants-only"
-licenseId GFDL_1_3_no_invariants_or_later = "GFDL-1.3-no-invariants-or-later"
-licenseId GFDL_1_3_only = "GFDL-1.3-only"
-licenseId GFDL_1_3_or_later = "GFDL-1.3-or-later"
-licenseId GPL_1_0_only = "GPL-1.0-only"
-licenseId GPL_1_0_or_later = "GPL-1.0-or-later"
-licenseId GPL_2_0_only = "GPL-2.0-only"
-licenseId GPL_2_0_or_later = "GPL-2.0-or-later"
-licenseId GPL_3_0_only = "GPL-3.0-only"
-licenseId GPL_3_0_or_later = "GPL-3.0-or-later"
-licenseId LGPL_2_0_only = "LGPL-2.0-only"
-licenseId LGPL_2_0_or_later = "LGPL-2.0-or-later"
-licenseId LGPL_2_1_only = "LGPL-2.1-only"
-licenseId LGPL_2_1_or_later = "LGPL-2.1-or-later"
-licenseId LGPL_3_0_only = "LGPL-3.0-only"
-licenseId LGPL_3_0_or_later = "LGPL-3.0-or-later"
-licenseId LGPLLR = "LGPLLR"
-licenseId LPPL_1_0 = "LPPL-1.0"
-licenseId LPPL_1_1 = "LPPL-1.1"
-licenseId LPPL_1_2 = "LPPL-1.2"
-licenseId LPPL_1_3a = "LPPL-1.3a"
-licenseId LPPL_1_3c = "LPPL-1.3c"
-licenseId MPL_1_0 = "MPL-1.0"
-licenseId MPL_1_1 = "MPL-1.1"
-licenseId MPL_2_0 = "MPL-2.0"
-licenseId PHP_3_0 = "PHP-3.0"
-licenseId PHP_3_01 = "PHP-3.01"
-licenseId PSF_2_0 = "PSF-2.0"
-licenseId Ruby = "Ruby"
-licenseId Unlicense = "Unlicense"
-licenseId W3C = "W3C"
-licenseId WTFPL = "WTFPL"
-licenseId ZPL_1_1 = "ZPL-1.1"
-licenseId ZPL_2_0 = "ZPL-2.0"
-licenseId ZPL_2_1 = "ZPL-2.1"
-licenseId (Custom x) = "custom:" <> x
+$(loadKnownSPDX)
 
-parseLicense :: Text -> License
-parseLicense "AGPL-3.0-only" = AGPL_3_0_only
-parseLicense "AGPL-3.0-or-later" = AGPL_3_0_or_later
-parseLicense "Apache-2.0" = Apache_2_0
-parseLicense "Artistic-1.0-Perl" = Artistic_1_0_Perl
-parseLicense "Artistic-2.0" = Artistic_2_0
-parseLicense "BSL-1.0" = BSL_1_0
-parseLicense "CC-BY-1.0" = CC_BY_1_0
-parseLicense "CC-BY-2.0" = CC_BY_2_0
-parseLicense "CC-BY-2.5" = CC_BY_2_5
-parseLicense "CC-BY-3.0-AT" = CC_BY_3_0_AT
-parseLicense "CC-BY-3.0-US" = CC_BY_3_0_US
-parseLicense "CC-BY-3.0" = CC_BY_3_0
-parseLicense "CC-BY-4.0" = CC_BY_4_0
-parseLicense "CC-BY-NC-1.0" = CC_BY_NC_1_0
-parseLicense "CC-BY-NC-2.0" = CC_BY_NC_2_0
-parseLicense "CC-BY-NC-2.5" = CC_BY_NC_2_5
-parseLicense "CC-BY-NC-3.0" = CC_BY_NC_3_0
-parseLicense "CC-BY-NC-4.0" = CC_BY_NC_4_0
-parseLicense "CC-BY-NC-ND-1.0" = CC_BY_NC_ND_1_0
-parseLicense "CC-BY-NC-ND-2.0" = CC_BY_NC_ND_2_0
-parseLicense "CC-BY-NC-ND-2.5" = CC_BY_NC_ND_2_5
-parseLicense "CC-BY-NC-ND-3.0-IGO" = CC_BY_NC_ND_3_0_IGO
-parseLicense "CC-BY-NC-ND-3.0" = CC_BY_NC_ND_3_0
-parseLicense "CC-BY-NC-ND-4.0" = CC_BY_NC_ND_4_0
-parseLicense "CC-BY-NC-SA-1.0" = CC_BY_NC_SA_1_0
-parseLicense "CC-BY-NC-SA-2.0" = CC_BY_NC_SA_2_0
-parseLicense "CC-BY-NC-SA-2.5" = CC_BY_NC_SA_2_5
-parseLicense "CC-BY-NC-SA-3.0" = CC_BY_NC_SA_3_0
-parseLicense "CC-BY-NC-SA-4.0" = CC_BY_NC_SA_4_0
-parseLicense "CC-BY-ND-1.0" = CC_BY_ND_1_0
-parseLicense "CC-BY-ND-2.0" = CC_BY_ND_2_0
-parseLicense "CC-BY-ND-2.5" = CC_BY_ND_2_5
-parseLicense "CC-BY-ND-3.0" = CC_BY_ND_3_0
-parseLicense "CC-BY-ND-4.0" = CC_BY_ND_4_0
-parseLicense "CC-BY-SA-1.0" = CC_BY_SA_1_0
-parseLicense "CC-BY-SA-2.0-UK" = CC_BY_SA_2_0_UK
-parseLicense "CC-BY-SA-2.1-JP" = CC_BY_SA_2_1_JP
-parseLicense "CC-BY-SA-2.5" = CC_BY_SA_2_5
-parseLicense "CC-BY-SA-3.0-AT" = CC_BY_SA_3_0_AT
-parseLicense "CC-BY-SA-3.0" = CC_BY_SA_3_0
-parseLicense "CC-BY-SA-4.0" = CC_BY_SA_4_0
-parseLicense "CC-PDDC" = CC_PDDC
-parseLicense "CC0-1.0" = CC0_1_0
-parseLicense "CDDL-1.0" = CDDL_1_0
-parseLicense "CDDL-1.1" = CDDL_1_1
-parseLicense "CPL-1.0" = CPL_1_0
-parseLicense "EPL-1.0" = EPL_1_0
-parseLicense "EPL-2.0" = EPL_2_0
-parseLicense "FSFAP" = FSFAP
-parseLicense "GFDL-1.1-invariants-only" = GFDL_1_1_invariants_only
-parseLicense "GFDL-1.1-invariants-or-later" = GFDL_1_1_invariants_or_later
-parseLicense "GFDL-1.1-no-invariants-only" = GFDL_1_1_no_invariants_only
-parseLicense "GFDL-1.1-no-invariants-or-later" = GFDL_1_1_no_invariants_or_later
-parseLicense "GFDL-1.1-only" = GFDL_1_1_only
-parseLicense "GFDL-1.1-or-later" = GFDL_1_1_or_later
-parseLicense "GFDL-1.2-invariants-only" = GFDL_1_2_invariants_only
-parseLicense "GFDL-1.2-invariants-or-later" = GFDL_1_2_invariants_or_later
-parseLicense "GFDL-1.2-no-invariants-only" = GFDL_1_2_no_invariants_only
-parseLicense "GFDL-1.2-no-invariants-or-later" = GFDL_1_2_no_invariants_or_later
-parseLicense "GFDL-1.2-only" = GFDL_1_2_only
-parseLicense "GFDL-1.2-or-later" = GFDL_1_2_or_later
-parseLicense "GFDL-1.3-invariants-only" = GFDL_1_3_invariants_only
-parseLicense "GFDL-1.3-invariants-or-later" = GFDL_1_3_invariants_or_later
-parseLicense "GFDL-1.3-no-invariants-only" = GFDL_1_3_no_invariants_only
-parseLicense "GFDL-1.3-no-invariants-or-later" = GFDL_1_3_no_invariants_or_later
-parseLicense "GFDL-1.3-only" = GFDL_1_3_only
-parseLicense "GFDL-1.3-or-later" = GFDL_1_3_or_later
-parseLicense "GPL-1.0-only" = GPL_1_0_only
-parseLicense "GPL-1.0-or-later" = GPL_1_0_or_later
-parseLicense "GPL-2.0-only" = GPL_2_0_only
-parseLicense "GPL-2.0-or-later" = GPL_2_0_or_later
-parseLicense "GPL-3.0-only" = GPL_3_0_only
-parseLicense "GPL-3.0-or-later" = GPL_3_0_or_later
-parseLicense "LGPL-2.0-only" = LGPL_2_0_only
-parseLicense "LGPL-2.0-or-later" = LGPL_2_0_or_later
-parseLicense "LGPL-2.1-only" = LGPL_2_1_only
-parseLicense "LGPL-2.1-or-later" = LGPL_2_1_or_later
-parseLicense "LGPL-3.0-only" = LGPL_3_0_only
-parseLicense "LGPL-3.0-or-later" = LGPL_3_0_or_later
-parseLicense "LGPLLR" = LGPLLR
-parseLicense "LPPL-1.0" = LPPL_1_0
-parseLicense "LPPL-1.1" = LPPL_1_1
-parseLicense "LPPL-1.2" = LPPL_1_2
-parseLicense "LPPL-1.3a" = LPPL_1_3a
-parseLicense "LPPL-1.3c" = LPPL_1_3c
-parseLicense "MPL-1.0" = MPL_1_0
-parseLicense "MPL-1.1" = MPL_1_1
-parseLicense "MPL-2.0" = MPL_2_0
-parseLicense "PHP-3.0" = PHP_3_0
-parseLicense "PHP-3.01" = PHP_3_01
-parseLicense "PSF-2.0" = PSF_2_0
-parseLicense "Ruby" = Ruby
-parseLicense "Unlicense" = Unlicense
-parseLicense "W3C" = W3C
-parseLicense "WTFPL" = WTFPL
-parseLicense "ZPL-1.1" = ZPL_1_1
-parseLicense "ZPL-2.0" = ZPL_2_0
-parseLicense "ZPL-2.1" = ZPL_2_1
-parseLicense x = Custom x
+licenseId :: License -> String
+parseLicense :: String -> License
 
 instance ToJSON License where
-  toJSON x = String $ licenseId x
+  toJSON x = String . T.pack $ licenseId x
 
 instance FromJSON License where
-  parseJSON = withText "License" $ \txt -> pure (parseLicense txt)
+  parseJSON = withText "License" $ \(T.unpack -> txt) -> pure (parseLicense txt)
 
 -- | Package details returned by 'Web.ArchLinux.API.getPackageDetails'.
 data PackageInformation = PackageInformation
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -1,5 +1,6 @@
 module Main (main) where
 
+import Control.Exception (SomeException, catch)
 import Network.HTTP.Client (Manager)
 import Network.HTTP.Client.TLS (newTlsManager)
 import Test.HUnit
@@ -20,9 +21,14 @@
       createTest "getAurInfo" manager $ getAurInfo ["arch-hs-git"]
     ]
 
-createTest :: HasBaseUrl k => String -> Manager -> APIClient k a -> Test
+createTest :: (HasBaseUrl k) => String -> Manager -> APIClient k a -> Test
 createTest tag manager action = TestLabel tag . TestCase $ do
-  result <- runAPIClient manager action
+  -- Retry up to 3 times in case of network errors or rate limiting
+  result <- retry 3 $ runAPIClient manager action
   case result of
     Right _ -> pure ()
     Left err -> assertFailure $ show err
+
+retry :: Int -> IO a -> IO a
+retry 0 action = action
+retry n action = action `catch` \(_ :: SomeException) -> retry (n - 1) action
