diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8240dd195599e4be774a53c06fb15295a5c9cf3a..6801c903a3c5386e9594c5bdcfa9e228d3ae8967 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,20 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [Unreleased]
 
+### Added
+
+- Configuration variable `ckanext.odsh.min_tag_length` indicating minimum characters allowed for tag length.
+- Configuration variable `ckanext.odsh.max_tag_length` indicating maximum characters allowed
+
 ### Removed
 
 - Removed Travis CI `bin/` directory, along with all associated Travis CI configuration files and scripts.
 - Removed the functionality that retrieved the current commit hash of the checked out Git repository for the extension. The commit hash was previously inserted into a custom API resource to provide external developers repository information.
 - Removed `ckanext.odsh.home` configuration variable.
-- The `tag_name_validator` function, responsible for validating tag names, has been removed. Tag names are no longer restricted by any validation checks, allowing for unrestricted input (according [DCAT-AP](https://www.dcat-ap.de/def/dcatde/2.0/spec/#datensatz-schlagwort)).
 - Removed `ckanext.odsh.upload_formats` configuration variable. Upload formats are now populated by EU-approved file formats.
 - Removed subject mappings and other subject related code used in Transparenzportal SH (TPSH).
 
 ### Changed
 
+- Tag names are no longer restricted by strict validation checks, allowing for nearly unrestricted input (according [DCAT-AP](https://www.dcat-ap.de/def/dcatde/2.0/spec/#datensatz-schlagwort)).
 - Reorganized default mapping and resource files for improved organization and maintenance. Mapping and config files (e.g., file formats) are now located in `ckanext/odsh/resources/`.
 - Refactor distribution/resource editing form to replace free-text format field with select field populated by EU-approved file formats.
-- Reorganized tests and helper TPSH specific code
+- Reorganized tests and helper TPSH specific code.
 - Migrated TPSH helpers to `helpers.py`.
 - Moved TPSH tests to `tests/` and legacy tests to `tests_wip`.
 
diff --git a/README.md b/README.md
index 330ab15567a138e92885185c63115c277659f086..f8ee14f348bbbfa0739651a05ba43ccbde9e1ec4 100644
--- a/README.md
+++ b/README.md
@@ -97,6 +97,8 @@ Parameter | Type | Default | Description
 `ckanext.odsh.download_proxy` | `string` | `None` | Use proxy server to access the web, e.g., `http://1.2.3.4:4123`.
 `ckanext.odsh.copy_remote_resources` | `boolean` | `False` | Indicates whether remote resources should be copied when creating a resource.
 `ckanext.odsh.lenient_with` | `string` | Empty string | Comma seperated list of organization IDs for which certain validations should be more lenient, e.g., `09871195-cd0a-4767-9396-276404c940d9,6389d8d9-4eed-472f-9220-4cc2dd82fb90`.
+`ckanext.odsh.min_tag_length` | `integer` | `2` | Minimum characters allowed for tag length.
+`ckanext.odsh.max_tag_length` | `integer` | `100` | Maximum characters allowed for tag length.
 `ckanext.odsh.testuser` | `string` | `None` | Name of user for testing.
 `ckanext.odsh.testuserpass` | `string` | `None` | Password of user for testing.
 
diff --git a/ckanext/odsh/tests_wip/test_validation.py b/ckanext/odsh/tests_wip/test_validation.py
index 746afc75da8b4c3d4514e205ed1ed7bed8d5545a..7e6a63000cacb30894f2dd2e992f44421909c80b 100644
--- a/ckanext/odsh/tests_wip/test_validation.py
+++ b/ckanext/odsh/tests_wip/test_validation.py
@@ -106,6 +106,7 @@ def test_validate_licenseAttributionByText():
             ('extras', 0, 'value'): ''}
     validate_licenseAttributionByText('key', data, {}, None)
 
+
 def test_tag_name_validator_invalid():
     with pytest.raises(Exception):
         tag_name_validator('Foo\nBar', None)
@@ -113,3 +114,27 @@ def test_tag_name_validator_invalid():
 
 def test_tag_name_validator_valid():
     tag_name_validator('Regionalplan für den Planungsraum_I: (5.8 – Windenergie_an_Land)', None)
+
+
+def test_tag_length_validator_invalid():
+    min = toolkit.config.get('ckanext.odsh.min_tag_length',2)
+    max = toolkit.config.get('ckanext.odsh.max_tag_length',100)
+    length = round((min + max) / 2)
+    test_string = _create_test_string(length)
+    with pytest.raises(Exception):
+        tag_length_validator(test_string, None)
+
+
+def test_tag_length_validator_valid():
+    max = toolkit.config.get('ckanext.odsh.max_tag_length',100)
+    length = max + 1
+    test_string = _create_test_string(length)
+    tag_length_validator(test_string, None)
+
+
+def _create_test_string(length):
+    base_string = "Lorem ipsum dolor sit amet."
+    num_repetitions = (length // len(base_string)) + 1
+    test_string = base_string * num_repetitions
+    test_string = test_string[:length]
+    return test_string
\ No newline at end of file
diff --git a/ckanext/odsh/validation.py b/ckanext/odsh/validation.py
index 32cd39e3f1e69b3b88b3e81a1fd42f8c1ab20039..a3da48191bbb67fb2f6b1289384a553d916188fd 100644
--- a/ckanext/odsh/validation.py
+++ b/ckanext/odsh/validation.py
@@ -288,7 +288,7 @@ def tag_string_convert(key, data, errors, context):
         data[('tags', num, 'name')] = tag
 
     for tag in tags:
-        toolkit.get_validator('tag_length_validator')(tag, context)
+        tag_length_validator(tag, context)
         tag_name_validator(tag, context)
 
 
@@ -310,6 +310,23 @@ def validate_formats(data, errors):
     return data
 
 
+def tag_length_validator(value, context):
+    """Ensures that tag length is in the acceptable range.
+    """
+    min_tag_length = tk.config.get('ckanext.odsh.min_tag_length',2)
+    max_tag_length = tk.config.get('ckanext.odsh.max_tag_length',100)
+
+    if len(value) < min_tag_length:
+        raise toolkit.Invalid(
+            _('Tag "%s" length is less than minimum %s') % (value, max_tag_length)
+        )
+    if len(value) > min_tag_length:
+        raise toolkit.Invalid(
+            _('Tag "%s" length is more than maximum %i') % (value, max_tag_length)
+        )
+    return value
+
+
 def tag_name_validator(value, context):
     """Allow tag name to contain any characters but no newlines
     """
@@ -327,4 +344,5 @@ def get_validators():
 	      'validate_relatedPackage': validate_relatedPackage,
         'odsh_validate_format': validate_formats,
         'tag_name_validator': tag_name_validator,
+        'tag_length_validator': tag_length_validator,
     }