diff --git a/pydatajson/constants.py b/pydatajson/constants.py
index dc49ecb..cbfbd03 100644
--- a/pydatajson/constants.py
+++ b/pydatajson/constants.py
@@ -1,6 +1,7 @@
 REQUESTS_TIMEOUT = 30
 DEFAULT_TIMEZONE = "America/Buenos_Aires"
 
-VALID_STATUS_CODES = [200, 203, 302]
+INVALID_STATUS_CODES_REGEX = ["^4[0-9]+$", "^5[0-9]+$"]
+EXCEPTION_STATUS_CODES = [429]
 
 CANT_THREADS_BROKEN_URL_VALIDATOR = 10
diff --git a/pydatajson/helpers.py b/pydatajson/helpers.py
index 638a9a8..dde2dea 100644
--- a/pydatajson/helpers.py
+++ b/pydatajson/helpers.py
@@ -18,13 +18,15 @@ from contextlib import contextmanager
 
 import requests
 from openpyxl import load_workbook
-from requests import RequestException
+from requests import RequestException, Timeout
 from six.moves.urllib_parse import urlparse
 
 from six import string_types, iteritems
 from unidecode import unidecode
 
-from pydatajson.constants import VALID_STATUS_CODES
+from pydatajson.constants import \
+    INVALID_STATUS_CODES_REGEX, \
+    EXCEPTION_STATUS_CODES
 from pydatajson.download import download_to_file
 
 logger = logging.getLogger('pydatajson.helpers')
@@ -571,6 +573,13 @@ def fields_to_uppercase(fields):
 def is_working_url(url):
     try:
         response = requests.head(url, timeout=1)
-        return response.status_code in VALID_STATUS_CODES, response.status_code
+        matches = []
+        if response.status_code not in EXCEPTION_STATUS_CODES:
+            matches = \
+                [re.match(pattern, str(response.status_code)) is not None
+                 for pattern in INVALID_STATUS_CODES_REGEX]
+        return True not in matches, response.status_code
+    except Timeout:
+        return False, 408
     except (RequestException, Exception):
         return False, None

Modificar criterio de análisis de broken URL: es válida a menos que 4xx o 5xx
Excepciones: 429 "Too Many Requests" no se debe considerar broken.
diff --git a/tests/test_helpers.py b/tests/test_helpers.py
index c5edfa6..5a7e91b 100644
--- a/tests/test_helpers.py
+++ b/tests/test_helpers.py
@@ -294,15 +294,23 @@ class HelpersTestCase(unittest.TestCase):
         req_mock.head('http://test.com/', status_code=400)
         self.assertEqual((False, 400), is_working_url('http://test.com/'))
 
+    @requests_mock.Mocker()
+    def test_validate_too_many_requests_response(self, req_mock):
+        too_many_request_status_code = 429
+        req_mock.head('http://test.com/',
+                      status_code=too_many_request_status_code)
+        self.assertEqual((True, too_many_request_status_code),
+                         is_working_url('http://test.com/'))
+
     @requests_mock.Mocker()
     def test_validate_url_with_exception(self, req_mock):
         req_mock.head('http://test.com/', exc=ConnectionError)
         self.assertEqual((False, None), is_working_url('http://test.com/'))
 
     @requests_mock.Mocker()
-    def validate_url_with_timeout(self, req_mock):
+    def test_validate_url_with_timeout(self, req_mock):
         req_mock.head('http://test.com/', exc=Timeout)
-        self.assertEqual((False, None), is_working_url('http://test.com/'))
+        self.assertEqual((False, 408), is_working_url('http://test.com/'))
 
     def test_validate_malformed_values(self):
 

pip install -e .[dev]
parse_log_pytest
requirements.txt
nose pytest
apt-get update apt-get install -y gcc
3.6
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
certifi==2021.5.30
charset-normalizer==2.0.12
ckanapi==4.0
docopt==0.6.2
et-xmlfile==1.1.0
idna==3.10
importlib-metadata==4.8.3
iniconfig==1.1.1
isodate==0.6.0
jsonschema==2.6.0
nose==1.3.7
openpyxl==3.1.3
packaging==21.3
pluggy==1.0.0
py==1.11.0
-e git+https://github.com/datosgobar/pydatajson.git@7ac9d34f7ecfe7b9804eba44626c7ac15606f09a#egg=pydatajson
pyparsing==3.1.4
pytest==7.0.1
python-dateutil==2.8.0
pytz==2025.2
requests==2.27.1
requests-mock==1.12.1
rfc3987==1.3.7
six==1.17.0
tomli==1.2.3
typing_extensions==4.1.1
unicodecsv==0.14.1
Unidecode==0.4.21
urllib3==1.26.20
zipp==3.6.0

name: pydatajson
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - charset-normalizer==2.0.12
      - ckanapi==4.0
      - docopt==0.6.2
      - et-xmlfile==1.1.0
      - idna==3.10
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - isodate==0.6.0
      - jsonschema==2.6.0
      - nose==1.3.7
      - openpyxl==3.1.3
      - packaging==21.3
      - pluggy==1.0.0
      - py==1.11.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - python-dateutil==2.8.0
      - pytz==2025.2
      - requests==2.27.1
      - requests-mock==1.12.1
      - rfc3987==1.3.7
      - six==1.17.0
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - unicodecsv==0.14.1
      - unidecode==0.04.21
      - urllib3==1.26.20
      - zipp==3.6.0
prefix: /opt/conda/envs/pydatajson

tests/test_helpers.py::HelpersTestCase::test_validate_too_many_requests_response tests/test_helpers.py::HelpersTestCase::test_validate_url_with_timeout
tests/test_helpers.py::HelpersTestCase::test_add_dicts tests/test_helpers.py::HelpersTestCase::test_fields_to_uppercase_keeps_uppercase_fields_intact tests/test_helpers.py::HelpersTestCase::test_fields_to_uppercase_modifies_all_lowercase_fields tests/test_helpers.py::HelpersTestCase::test_fields_to_uppercase_modifies_mixed_fields tests/test_helpers.py::HelpersTestCase::test_fields_to_uppercase_returns_unique_uppercase_keys tests/test_helpers.py::HelpersTestCase::test_is_list_of_matching_dicts_with_list_of_not_dicts tests/test_helpers.py::HelpersTestCase::test_is_list_of_matching_dicts_with_matched_dicts tests/test_helpers.py::HelpersTestCase::test_is_list_of_matching_dicts_with_mismatched_dicts tests/test_helpers.py::HelpersTestCase::test_is_list_of_matching_dicts_with_not_list tests/test_helpers.py::HelpersTestCase::test_parse_date_string tests/test_helpers.py::HelpersTestCase::test_parse_repeating_time_interval_to_days tests/test_helpers.py::HelpersTestCase::test_parse_repeating_time_interval_to_str tests/test_helpers.py::HelpersTestCase::test_sheet_to_table tests/test_helpers.py::HelpersTestCase::test_string_to_list_alternative_separator tests/test_helpers.py::HelpersTestCase::test_string_to_list_default_separator tests/test_helpers.py::HelpersTestCase::test_title_to_name tests/test_helpers.py::HelpersTestCase::test_traverse_dict_correct_keys tests/test_helpers.py::HelpersTestCase::test_traverse_dict_index_out_of_range tests/test_helpers.py::HelpersTestCase::test_traverse_dict_missing_key tests/test_helpers.py::HelpersTestCase::test_traverse_dict_string_index_for_list tests/test_helpers.py::HelpersTestCase::test_validate_invalid_url tests/test_helpers.py::HelpersTestCase::test_validate_malformed_values tests/test_helpers.py::HelpersTestCase::test_validate_url_with_exception tests/test_helpers.py::HelpersTestCase::test_validate_valid_url
pydatajson/constants.py pydatajson/helpers.py
pydatajson/constants.py pydatajson/helpers.py