La página de repositorios de GitHub expone pushed_at, una marca de tiempo que puede cambiar cuando cualquier rama recibe un push. Eso puede no coincidir con el commit más reciente en la rama por defecto. La fecha de la rama principal es una señal de mantenimiento del repositorio; no necesariamente corresponde al código que termina instalando un gestor de paquetes.
Los gestores de paquetes suelen resolver artefactos del registro o versiones de módulos. Por eso esta auditoría revisa por separado la actividad del repositorio y el artefacto publicado: cualquiera de los dos puede estar al día mientras el otro ya quedó obsoleto.
Así que tomé 35 repos que todavía aparecen en recomendaciones y revisé el dato que GitHub no muestra en el encabezado: la fecha del commit más reciente en la rama por defecto.
La discrepancia es real: 14 de los 35 tienen un pushed_at más de 180 días por delante del último commit de la rama por defecto, con un máximo de 1.802 días. En tres de esos 14 se confirmó la presencia de bots; tras excluir repos archivados y filtrar actividad humana, quedan dos casos confirmados de bots entre nueve candidatos. Lo más útil de todo esto es que la vigencia del repositorio y la del artefacto publicado pueden ir por caminos distintos.
Qué se midió y sobre qué base

Referencia oficial: GitHub repository API.
Todas las cifras de este artículo se leyeron desde respuestas reales de la API entre las 15:44 y las 15:53 UTC del 2026-07-27 y se almacenaron en caché. El dataset de 35 filas, la lista de repositorios, las filas generadas y los scripts de obtención y construcción en artifacts/ conservan tanto los datos de entrada como el código de transformación de la auditoría.
Se recopilaron cuatro categorías de datos; las consultas al registro y a la actividad fueron condicionales, no una secuencia uniforme de cuatro llamadas:
GET /repos/{owner}/{repo}— estrellas,archived,pushed_at, licencia ydefault_branch.GET /repos/{o}/{r}/commits?sha={default_branch}&per_page=1— el commit más reciente de la rama por defecto, usado como señal de mantenimiento del repositorio.GET /repos/{o}/{r}/activity?per_page=30— para cada repositorio en el que esos dos datos no coincidían, qué fue realmente lo que moviópushed_at.GET /repos/{o}/{r}/releasesjunto con los registros de PyPI y npm — cuándo se publicó por última vez el artefacto, que al final resulta más relevante que cualquiera de los otros dos.
staleness_days es el tiempo transcurrido desde el commit de la rama por defecto hasta el momento de referencia. La diferencia entre pushed_at y ese commit es la ilusión, medida en días. Todo lo que supera 180 días queda marcado.
Hay dos principios que conviene dejar claros porque cambiaron los resultados.
La atribución de paquetes se verificó, nunca se supuso. Que el README de un paquete mencione un repositorio no significa que ese sea su paquete. Cada relación tuvo que confirmarse con un campo estructurado —la entrada repository/project_urls del propio registro o un manifiesto comprometido dentro del repo. Seis asignaciones aparentemente plausibles no superaron esa prueba, y sus descargas no se atribuyen deliberadamente.
Uno de esos rechazos justifica por sí solo la regla. curl-cffi recibe 35.763.529 descargas al mes y, a simple vista, parece el binding de Python para lwthiker/curl-impersonate —un repo congelado desde hace 875 días. Atribuirlo habría arrojado una cifra cuarenta y cuatro veces mayor que la de newspaper3k, y habría sido falsa: los metadatos de PyPI de curl-cffi apuntan a lexiforest/curl_cffi, un proyecto distinto y activamente mantenido que se publicó por última vez el 2026-04-03. El número más espectacular disponible aquí era el equivocado.
Hay un séptimo caso aún más raro: steel-dev/steel-mcp-server declara @steel-dev/mcp-server en su propio package.json, pero npm devuelve 404. Nunca se publicó, así que no puede decirse que “siga instalándose”.
Cuando no se pudo obtener un dato, se indica. Las herramientas de Go, JVM, .NET y PHP no tienen presencia en PyPI ni npm, por lo que llevan N/A (no PyPI/npm package) —nunca cero. Diecisiete de los 35 no publican ningún GitHub Release; eso se registra como none, no como dato faltante.
Estos campos no se colapsan a propósito en un único “índice de salud”. Una rama principal obsoleta, una rama secundaria reciente, la ausencia de GitHub Releases y un artefacto de registro antiguo responden preguntas distintas. La evidencia fila por fila está disponible en el dataset de 35 filas, junto con los repositorios de entrada y los registros generados. Léelos como señales de triaje que indican el siguiente paso, no como cuatro votos sobre si un proyecto está vivo.
La advertencia sobre la muestra, desde el principio
Esta es una lista elaborada a mano de herramientas que sospeché que seguían a flote por reputación. No es una muestra aleatoria del ecosistema de scraping, y “31 de 35 están obsoletos” no es una tasa del ecosistema —es, más bien, una medida de lo bien que elegí la muestra. El resultado interesante no es el conteo de obsoletos, sino que incluso en una muestra seleccionada para ese fenómeno, el mecanismo concreto que estaba probando explicó solo una minoría de casos, y se pudo confirmar de forma positiva en todavía menos.
La ilusión es real, y este es su peor caso
sjdirect/abot, un crawler .NET con 2.308 estrellas. GitHub muestra un push el 2026-07-17, diez días antes de la fecha de referencia. La rama por defecto fue modificada por última vez el 2021-08-09.
Eso deja una brecha de 1.802 días. Cinco años. El encabezado dice “la semana pasada”.
Catorce de los 35 repos muestran una diferencia superior a 180 días:
| Repo | Brecha (días) | Último cambio en la rama por defecto | pushed_at |
|---|---|---|---|
sjdirect/abot | 1.802 | 2021-08-09 | 2026-07-17 |
dragnet-org/dragnet | 1.520 | 2021-05-09 | 2025-07-08 |
paquettg/php-html-parser | 1.376 | 2020-11-01 | 2024-08-09 |
seomoz/simhash-py | 1.159 | 2020-03-12 | 2023-05-15 |
internetarchive/wayback | 1.039 | 2021-04-27 | 2024-03-01 |
Rhizome-Conifer/conifer | 1.013 | 2023-10-12 | 2026-07-22 |
kohlschutter/boilerpipe | 856 | 2015-08-30 | 2018-01-03 |
scrapinghub/splash | 819 | 2022-05-05 | 2024-08-02 |
tomnomnom/waybackurls | 756 | 2022-04-05 | 2024-05-01 |
geziyor/geziyor | 689 | 2024-08-12 | 2026-07-02 |
crawlab-team/crawlab | 488 | 2024-10-09 | 2026-02-10 |
ArchiveTeam/wpull | 468 | 2023-01-16 | 2024-04-29 |
yasserg/crawler4j | 396 | 2020-10-03 | 2021-11-04 |
apache/any23 | 381 | 2022-06-03 | 2023-06-20 |
Catorce de treinta y cinco. Es real, conviene conocerlo y es una minoría dentro de una muestra elegida precisamente para contenerlo.
Se confirmaron bots en tres repositorios marcados —y quedan dos tras filtrar
La versión popular de esta historia siempre menciona dependabot. Lo verifiqué descargando el feed de actividad de cada repo marcado y clasificando cada ref enviada después del último commit de la rama por defecto. Ese “después” importa: los eventos anteriores al último commit no dicen nada sobre qué infló la brecha, y contar todo el feed cambia silenciosamente la pregunta.
Confirmados como impulsados por bots, con el método posterior al commit: tres. scrapinghub/splash (4 de 4 eventos posteriores al commit en dependabot/pip/*), geziyor/geziyor (5 de 5 en dependabot/go_modules/*), apache/any23 (16 de 16 en dependabot/maven/*). Uno de esos tres, any23, está archivado formalmente, así que nunca entra en el subconjunto filtrado —lo que deja dos casos confirmados que además cumplen todas las demás condiciones.
Directamente incorrectos: dos, y ambos son más interesantes que la historia del bot.
La brecha de 1.520 días de dragnet-org/dragnet proviene de una persona que empujó una rama llamada mp/py3.10 —un port a Python 3.10 que nunca se fusionó. Alguien intentó llevarlo adelante y se detuvo. Eso no es ruido automatizado inflando una marca de tiempo; es un registro visible y fechado de un intento de rescate fallido. Se podría decir que es la señal más útil de todo el conjunto, y el encuadre “dependabot lo hizo” la habría borrado.
Mixto, y más grande que cualquiera de las dos explicaciones: dos. crawlab-team/crawlab tiene 12.250 estrellas —el segundo repositorio con más estrellas de la muestra— y una brecha de 488 días en main. Su feed incluye ramas de dependabot y 24 pushes posteriores al commit hechos por humanos, todos a develop y test. Quien vea el encabezado lee febrero de 2026 y asume que sigue vivo; quien vea main lee octubre de 2024 y asume que murió. Ambos se equivocan. El desarrollo se movió fuera de la rama por defecto, algo que los proyectos hacen y que la vista resumida de GitHub no sabe expresar. sjdirect/abot es el otro caso mixto: el push que fijó su pushed_at principal sí fue de dependabot, pero una persona empujó upgrade1 en 2024, por eso más adelante queda fuera del grupo filtrado.
Rhizome-Conifer/conifer es el caso ambiguo, y al principio lo interpreté mal. Su rama por defecto es main, no master, y main no se ha movido desde 2023-10-12 —el único evento main en el feed es la creación de una rama en enero de 2025, consistente con un cambio de nombre. Mientras tanto, una sola cuenta hizo push a conifer-twilight y twilight/read-only el 2026-07-22, cinco días antes de la fecha de referencia. Eso es actividad humana real, pero “en desarrollo activo” es más de lo que permiten las referencias. Un único colaborador, en ramas llamadas read-only, encaja al menos tan bien con un cierre gestionado como con un desarrollo en curso. Lo que sí puede afirmarse, y sigue valiendo la pena decir, es lo siguiente: la brecha de 1.013 días no es ruido de bots, pero tampoco prueba abandono.
Desconocidos: siete. php-html-parser, simhash-py, internetarchive/wayback, boilerpipe, waybackurls, wpull y crawler4j presentan una brecha verificada y un feed de actividad que devuelve vacío.
La explicación tentadora es la retención: el feed de actividad de GitHub no llega eternamente hacia atrás. El caché refuta eso para la mayoría de ellos. El evento más antiguo de las 123 respuestas es del 2023-03-10, y cinco de los siete tienen un pushed_at claramente dentro de esa ventana: php-html-parser 2024-08-09, wpull 2024-04-29, waybackurls 2024-05-01, internetarchive/wayback 2024-03-01, simhash-py 2023-05-15. Lo que haya movido esas marcas de tiempo debería haber aparecido en el feed y no apareció. La retención solo explica boilerpipe (2018) y crawler4j (2021).
Así que la afirmación honesta es más estrecha que una explicación pulida: para siete repositorios, la brecha es un hecho verificado y su causa no está establecida —el endpoint no devolvió nada, y en cinco de ellos no puedo decir por qué. “Fue dependabot” es una suposición para los siete.
En conjunto, entre los 14 repos marcados:
Causa del pushed_at inflado | Repos | Cuáles, y con qué evidencia |
|---|---|---|
| Confirmado como impulsado por bots | 3 | scrapinghub/splash (4 de 4 eventos posteriores al commit en dependabot/pip/*), geziyor/geziyor (5 de 5 en dependabot/go_modules/*), apache/any23 (16 de 16 en dependabot/maven/*) — any23 está archivado, lo que deja dos que además cumplen todas las demás condiciones |
| Mixto, bots y humanos | 2 | crawlab-team/crawlab (ramas de dependabot más 24 pushes posteriores al commit hechos por humanos, todos a develop y test), sjdirect/abot (el push que fijó su pushed_at principal sí fue de dependabot, pero una persona empujó upgrade1 en 2024) |
| Directamente incorrecto — trabajo humano, cero ramas de bots | 2 | dragnet-org/dragnet (3 eventos posteriores al commit, 0 en una rama de bot) — una persona empujó mp/py3.10, un port a Python 3.10 sin fusionar. Rhizome-Conifer/conifer (30 eventos posteriores al commit, 0 en una rama de bot) — una sola cuenta hizo push a conifer-twilight y twilight/read-only el 2026-07-22. Que conifer esté abandonado sigue siendo ambiguo, como se explicó arriba; lo que no es ambiguo es que ningún bot infló su pushed_at |
| Sin establecer — feed de actividad vacío | 7 | php-html-parser, simhash-py, internetarchive/wayback, boilerpipe, waybackurls, wpull, crawler4j |
Las filas suman 14. Clasifican qué movió pushed_at; no establecen por sí solas si un proyecto está abandonado.
Qué sobrevive al filtro completo, y qué significa “sobrevive”
La afirmación original necesita cuatro cosas a la vez: estar obsoleto más de un año, tener un pushed_at inflado más de 180 días, no estar archivado y no mostrar señales de que la inflación provenga de trabajo humano. Nueve de los 35 candidatos superan las cuatro, listados aquí junto a las dos exclusiones más importantes:
| Repo | ¿Cumple las cuatro? | Evidencia positiva de que bots inflaron el dato |
|---|---|---|
splash | sí | sí — 4 de 4 eventos posteriores al commit en dependabot/pip/* |
waybackurls | sí | ninguna en ningún sentido |
crawler4j | sí | ninguna en ningún sentido |
geziyor | sí | sí — 5 de 5 en dependabot/go_modules/* |
php-html-parser | sí | ninguna en ningún sentido |
boilerpipe | sí | ninguna en ningún sentido |
wpull | sí | ninguna en ningún sentido |
internetarchive/wayback | sí | ninguna en ningún sentido |
simhash-py | sí | ninguna en ningún sentido |
any23 | no — archivado | sí — 16 de 16 en dependabot/maven/*, la confirmación más fuerte de toda la auditoría |
abot | no — su historial contiene un push humano (upgrade1, 2024) | mixto — el push que fijó su pushed_at principal sí fue de dependabot |
Ese número necesita una aclaración que el filtro no puede cargar. Solo dos de los nueve — splash y geziyor — tienen evidencia positiva de que bots inflaron el dato. Los otros siete superan la cuarta condición por ausencia de evidencia en cualquiera de los dos sentidos. Son casos que la afirmación deja pasar, no casos que la confirman. Y la confirmación más fuerte de toda la auditoría, any23 con 16 de 16 eventos de dependabot, queda fuera porque el repositorio está archivado.
Además, abot, el caso de 1.802 días, no está entre los nueve. Su registro contiene un push humano, así que no cumple la cuarta condición —la ilusión más llamativa del conjunto no es un ejemplo limpio del mecanismo que pretende ilustrar.
Para 21 de 35, GitHub sí mostró la obsolescencia con claridad
Este es el hallazgo que más daño hizo a mi hipótesis. Catorce repositorios tienen una brecha exactamente igual a cero, y otros siete están por debajo de 180 días. Para 21 de los 35 candidatos, pushed_at sí coincide con el último commit de la rama por defecto. GitHub no está ocultando nada.
Incluyendo algunas de las cosas más muertas de la muestra:
| Repo | Estrellas | Obsoleto (días) | Brecha |
|---|---|---|---|
Janpot/microdata-node | 57 | 1.866 | 0 |
1e0ng/simhash | 1.037 | 1.606 | 21 |
ekzhu/SetSimilaritySearch | 603 | 1.384 | 0 |
GerbenJavado/LinkFinder | 4.431 | 834 | 0 |
hakluke/hakrawler | 5.099 | 582 | 0 |
lavague-ai/LaVague | 6.388 | 551 | 0 |
my8100/scrapydweb | 3.411 | 522 | 0 |
getomni-ai/zerox | 12.258 | 432 | 0 |
scrapinghub/frontera | 1.332 | 415 | 0 |
BuilderIO/gpt-crawler | 22.374 | 384 | 0 |
BuilderIO/gpt-crawler tiene 22.374 estrellas y su encabezado dice lo mismo desde el 2025-07-07. No se oculta nada, y el volumen de instalaciones sigue.
Eso obliga a reducir la tesis a algo más preciso: GitHub oculta la obsolescencia en una minoría de casos, y en la mayoría la muestra con claridad aunque las instalaciones sigan igual. Por qué siguen no lo puede responder este conjunto de datos —aquí se cuentan instalaciones, no decisiones—. Pero ningún cambio de interfaz resuelve el segundo grupo, que es el más grande.
La actividad del repositorio y el artefacto publicado pueden separarse
La fila más llamativa del conjunto rompe por completo el encuadre.
codelucas/newspaper —15.126 estrellas— está activo. Su último commit en la rama por defecto es del 2026-07-21, frente a una fecha de referencia del 2026-07-27, y fue escrito por la persona que mantiene el proyecto. Todas las comprobaciones a nivel de repositorio pasan.
El paquete que todo el mundo instala es newspaper3k 0.2.8, publicado el 2018-09-28. Tiene 2.858 días y recibe 813.513 descargas al mes.
La rama por defecto está al día, mientras que el artefacto de PyPI no se publica desde 2018. Esto demuestra una brecha de publicación, no por qué el paquete no se ha vuelto a publicar ni si hay una canalización rota. Es el tipo de riesgo que una revisión de mantenimiento basada solo en el repositorio no vería, porque el artefacto del registro es lo que normalmente se ejecuta después de pip install newspaper3k.
Una vez que miras paquetes en vez de repositorios, el patrón aparece por todas partes. Entre los 17 paquetes cuya atribución al repositorio pudo verificarse, 16 se publicaron por última vez hace más de un año, y esos 16 representan aproximadamente 2,28 millones de instalaciones al mes sobre un total de 2,30 millones:
| Paquete | Instalaciones/mes | Última publicación | Edad del paquete (días) |
|---|---|---|---|
newspaper3k | 813.513 | 2018-09-28 | 2.858 |
tls-client | 790.305 | 2024-02-02 | 905 |
simhash | 317.615 | 2022-03-03 | 1.606 |
microdata-node | 204.025 | 2020-05-11 | 2.267 |
@modelcontextprotocol/server-puppeteer | 127.232 | 2025-05-12 | 440 |
extract-thinker | 10.927 | 2025-06-09 | 412 |
SetSimilaritySearch | 7.984 | 2022-10-11 | 1.384 |
frontera | 4.709 | 2019-04-05 | 2.669 |
zerox | 3.303 | 2025-05-20 | 432 |
scrapydweb | 1.163 | 2025-02-16 | 525 |
lavague | 606 | 2024-08-05 | 720 |
splash | 333 | 2020-06-16 | 2.231 |
dragnet | 213 | 2019-04-16 | 2.658 |
@builder.io/gpt-crawler | 137 | 2025-01-23 | 549 |
lmnr-index | 120 | 2025-06-05 | 416 |
simhash-py | 113 | 2017-03-22 | 3.413 |
tls-client merece su propia línea: 790.305 instalaciones al mes desde un repo congelado hace 905 días, en una categoría donde mantenerse al día es literalmente el trabajo. El comportamiento TLS del navegador cambia; una librería que dejó de seguirlo a comienzos de 2024 funciona con supuestos de comienzos de 2024.
Dos cautelas sobre esta tabla. Los conteos de descargas del registro incluyen ejecuciones de CI y espejos, y no desduplican nada, así que miden volumen de instalación, no personas. Además, las ventanas no comparten fecha de cierre —las de npm llegan hasta el 2026-07-24, las de pypistats son relativas al momento de la consulta—, así que el total es la suma de meses ligeramente desfasados y conviene leerlo como “unos 2,28 millones”, no al detalle de la cifra.
El choque de nombres que conviene conocer
internetarchive/wayback es el viejo OpenWayback de Java, congelado desde hace 1.916 días. wayback en PyPI es otro proyecto completamente distinto —edgi-govdata-archiving/wayback— y está sano, con la versión 0.5.1 publicada el 2026-06-19, cinco semanas antes de la fecha de referencia. Mismo nombre, condición opuesta, sin relación entre sí. Esta fue una de las seis atribuciones rechazadas, y es la que más fácil puede confundir a un usuario real: buscar el nombre te devuelve ambos, y en ninguna página se indica cuál encontraste.
Archivado, deprecado y todavía instalado 127.232 veces al mes
Seis repositorios de la muestra tienen archived: true, que GitHub muestra con una franja a todo lo ancho. Mi primera lectura fue que eso demostraba que la gente ignora las advertencias llamativas. La caché dice que la historia es peor que eso.
Referencia oficial: documentación de la API de conteo de descargas de npm.
Referencia oficial: documentación de deprecación de npm.
@modelcontextprotocol/server-puppeteer recibe 127.232 instalaciones al mes desde modelcontextprotocol/servers-archived. Pero su campo repository en npm es null —no hay un enlace desde la página del paquete de vuelta al repo, así que la franja no es algo que un instalador pueda simplemente saltarse. La mayoría de quienes instalan este paquete nunca tuvieron una ruta que los llevara hasta allí.
Lo que sí publica npm es la deprecación. La versión más reciente del paquete lleva deprecated: "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info." —y npm lo imprime en la terminal durante la instalación. Así que la advertencia sí se entrega, en el lugar donde el usuario realmente está, y aun así siguen ocurriendo 127.232 instalaciones al mes. Es un hallazgo más sólido que el de la franja del repositorio, y apunta a otra conclusión: la señal no falta, sino que llega dentro de una pared de salida de instalación que nadie obliga a leer.
browserbase/mcp-server-browserbase muestra cómo se ve un cierre limpio: su último commit en la rama por defecto, del 2026-07-20, dice literalmente “Mark repository as archived and unmaintained (#198)”. Los mantenedores lo anunciaron, lo fecharon y lo marcaron en la API. Sus 20.389 instalaciones merecen leerse con cuidado, sin embargo: la ventana de npm va del 2026-06-25 al 2026-07-24, así que 26 de esos 30 días son anteriores al commit de archivado. Esa cifra refleja sobre todo demanda previa al anuncio, no desobediencia. Lo que ocurre después no se puede saber de forma fiable con esta instantánea, y necesitaría una segunda lectura dentro de un mes antes de afirmar nada.
57 estrellas, 204.025 instalaciones al mes
Janpot/microdata-node tiene 57 estrellas y recibe 204.025 descargas al mes desde una publicación fechada el 2020-05-11.
Con solo 57 estrellas, microdata-node tiene poca visibilidad en el repositorio en relación con su volumen en el registro. La proporción de 3.579 instalaciones por estrella es compatible con uso transitivo, repeticiones en CI, espejos o consumo directo por máquinas. Esta auditoría no obtuvo gráficas de dependencias y no puede elegir entre esas explicaciones.
La fila es una invitación a revisar la exposición indirecta, pero demostrar uso transitivo requiere evidencia de dependencias inversas o de lockfiles, y esta auditoría no la recopiló.
Obsoleto no es lo mismo que roto
Una auditoría honesta tiene que decirlo: nada de esto mide si algo está roto. Mide si todavía hay alguien al volante.
Algunos de estos proyectos simplemente ya cumplieron su cometido. SetSimilaritySearch implementa algoritmos de similitud de conjuntos; eso no “se pudre”. simhash se basa en un paper de 2007. El algoritmo de extracción de contenido de boilerpipe se comporta en 2026 igual que en 2015 —más allá de su precisión frente a páginas modernas, el código no se ha desalineado bajo tus pies.
Lo que sí envejece mal es todo lo que depende de un objetivo en movimiento al otro lado:
- Automatización de navegador —cada versión de Chrome puede romperla.
- Comportamiento de clientes HTTP que imitan navegadores reales —los navegadores cambian, y una librería congelada deja de coincidir;
tls-cliententra aquí. - Analizadores específicos de sitios y reglas de extracción por sitio —cada rediseño de un sitio es un bug.
- Cualquier cosa que envuelva una API de terceros —el proveedor cambia el esquema y te enteras en producción.
- Cualquier cosa que envuelva un LLM —las deprecaciones de modelos se mueven más rápido que todo esto.
Así que “1.606 días obsoleto” es una alarma de cinco incendios para una categoría y casi irrelevante para una utilidad de hashing. Aquí no se probó ninguna rotura y no se hace ninguna afirmación sobre ella; ordenar tus dependencias por la categoría a la que pertenecen no cuesta nada y te ayuda más que el número de obsolescencia por sí solo.
Las cuatro comprobaciones que sí responden la pregunta

Ninguna es el encabezado del repositorio.
| # | Comprobación | Dónde leerla | Qué detecta |
|---|---|---|---|
| 1 | El último commit en la rama por defecto | GET /repos/{owner}/{repo}/commits?sha={default_branch}&per_page=1 | El dato que no te muestran. |
| 2 | La última vez que se publicó el artefacto | pypi.org/pypi/{pkg}/json o registry.npmjs.org/{pkg} → versión más reciente y su fecha de subida | Esto es lo que descubre a newspaper3k, y la comprobación 1 nunca lo hará. Ya que estás ahí, revisa también el campo deprecated de npm, que es como @modelcontextprotocol/server-puppeteer se anuncia. |
| 3 | La bandera archived | Un solo campo en la respuesta del repo, inequívoco y gratuito | Ojo: solo sirve si llegaste al repo, algo que los paquetes con repository: null no te permiten. |
| 4 | La brecha entre 1 y 2 | — (derivada de las dos anteriores) | Un repo con commits recientes y una publicación de hace tres años es un fallo distinto de uno simplemente congelado: significa que la persona mantenedora sigue ahí pero no está publicando. Eso es una decisión que tomar con los ojos abiertos, no una alerta por sí sola. La misma lógica se aplica a la inversa en crawlab: hay que comprobar si el trabajo se movió a una rama distinta de la por defecto antes de concluir nada. |
Ejecuta las comprobaciones 1, 2 y 3 como triaje rápido. Luego escala si faltan metadatos del repositorio, si la atribución del paquete es ambigua, si la actividad se movió a una rama que no es la por defecto o si el artefacto del registro diverge del repositorio. Los límites sin autenticación de GitHub y la latencia del registro hacen que prometer una respuesta en un segundo no sea realista.
Si una comprobación devuelve algo frío en una categoría que cambia rápido, las alternativas mantenidas en este espacio están documentadas en nuestras propias pruebas: Trafilatura para la extracción de contenido que antes hacían dragnet y boilerpipe, Scrapy o Crawlee para frameworks de crawling, Crawl4AI y Firecrawl para extracción orientada a LLM, y Scrapling cuando la resiliencia importa. Nuestro pilar de scrapers open source cubre el panorama más amplio. Son reseñas de primera mano; ejecuta tú mismo las cuatro comprobaciones antes de confiar en cualquier recomendación, incluida la nuestra.
Límites de estos datos
- Selección de la muestra. Elegida a mano por sospecha de abandono. No se puede leer de ahí ninguna tasa del ecosistema.
- Sin pruebas de rotura. Ninguna de estas 35 herramientas se ejecutó contra un sitio real. La obsolescencia es una señal de mantenimiento, no un veredicto funcional.
- Los conteos de descargas incluyen máquinas. CI, espejos, sin desduplicación y con ventanas que no comparten fecha de cierre. Volumen de instalación, no usuarios, y no decisiones.
- Las siete causas desconocidas siguen sin conocerse. El feed de actividad no devolvió nada, y en cinco de las siete la retención no lo explica. Dejar la celda vacía es mejor que rellenarla con la suposición popular.
staleness_daysusa fechas de commit. Un historial reescrito o con fechas manipuladas lo distorsionaría. No se detectó nada de eso, lo cual no es lo mismo que afirmar que no exista.- Una sola fecha de referencia. 2026-07-27. Varios de estos repositorios habrán cambiado cuando leas esto —
newspaper, en particular, hace commits con regularidad. Vuelve a ejecutar las cuatro comprobaciones; no cites mis fechas.
Cómo cambia esto con un servicio gestionado
Cada comprobación aquí existe porque, con una biblioteca autogestionada, la obsolescencia te pertenece a ti. Si un cliente HTTP congelado deja de comportarse como un navegador actual, ese incidente es tuyo, a la hora que sea que aparezca.
Nota del autor: Thunderbit es nuestro producto de scraping gestionado. Un servicio gestionado traslada parte de la responsabilidad de mantenimiento al proveedor, pero la cobertura, el tiempo de respuesta, el bloqueo con el proveedor y su continuidad pasan a formar parte del modelo de riesgo. Thunderbit no se evaluó en esta auditoría de repositorios.
El intercambio honesto es este: renuncias a leer el código, fijar una versión y arreglarlo tú mismo a las 2 de la mañana. Para un equipo que ya mantiene scrapers, la vía open source suele ser la decisión correcta —las cuatro comprobaciones son la forma de convertir eso en una decisión y no en una suposición.
Prueba Thunderbit para extraer datos web
Versión corta
Hice una lista para demostrar que GitHub oculta el abandono. La ilusión es real en 14 de 35 repositorios y espectacular en un caso: sjdirect/abot muestra un push de la semana pasada frente a una rama por defecto congelada desde 2021, una brecha de 1.802 días.
Pero el mecanismo es más estrecho que la historia. Nueve repositorios cumplen todas las condiciones que exige la afirmación, y solo dos de esos nueve —splash y geziyor— tienen evidencia positiva de que bots inflaron el dato; el resto supera la prueba por ausencia de evidencia. Dos repos marcados muestran a humanos intentando y fallando en revivir un proyecto. Uno, crawlab, tiene 12.250 estrellas y simplemente movió el desarrollo a develop. En siete, el feed de actividad volvió vacío y la retención no explica cinco de ellos, así que la causa queda sin establecer y no se asume. Y para 21 de 35 repositorios, GitHub informó la obsolescencia con precisión.
El peor caso del conjunto pasa todas las comprobaciones a nivel de repositorio. codelucas/newspaper fue comprometido el 2026-07-21; newspaper3k, publicado por última vez el 2018-09-28, salió 813.513 veces ese mes. En la muestra, 16 paquetes con publicaciones de más de un año de antigüedad concentran aproximadamente 2,28 millones de instalaciones al mes.
Revisa el commit de la rama por defecto, la fecha de publicación del registro, la bandera de archivado y el campo de deprecación de npm como triaje inicial. Después, resuelve la atribución paquete-repositorio y la actividad fuera de la rama por defecto antes de sacar conclusiones.
Prueba Thunderbit para extraer datos web Get Started Free
FAQs
¿Qué es pushed_at y por qué no significa “última actualización”?
pushed_at es el campo de la API de GitHub que alimenta la marca de actividad del repositorio, y se actualiza cuando se hace push a cualquier rama. El commit más reciente de la rama por defecto es solo una señal de mantenimiento del repositorio, mientras que los gestores de paquetes normalmente instalan artefactos del registro o versiones de módulos resueltas. En esta auditoría, 14 de los 35 repositorios mostraron una diferencia de más de 180 días entre esas dos fechas de GitHub.
¿Siempre es dependabot el que infla esa marca de tiempo?
No, y esa resultó ser la parte más débil de la historia popular. Contando solo los eventos que ocurrieron después del último commit de la rama por defecto, se confirmó la presencia de bots en 3 de los 14 repos marcados (splash 4 de 4, geziyor 5 de 5, any23 16 de 16). En 2 casos la explicación es directamente errónea: la brecha de dragnet viene de una persona que empujó un port sin fusionar a Python 3.10. Otros dos son mixtos, incluido crawlab, donde 24 pushes humanos fueron a develop y test mientras main permanecía quieta. Y en 7 el feed de actividad no devolvió nada, así que la causa no está establecida —la retención solo explica dos de esos siete.
¿Un repo obsoleto significa que la herramienta está rota?
No con esta evidencia: nada de esto se ejecutó contra un sitio real. La obsolescencia importa en proporción a la rapidez con que cambia el objetivo: la automatización de navegadores, los clientes HTTP que imitan el comportamiento de navegadores, los analizadores específicos por sitio y los envoltorios de API/LLM envejecen deprisa, mientras que librerías algorítmicas como SetSimilaritySearch o simhash pueden ser antiguas durante años y seguir perfectamente bien. tls-client es el caso más llamativo de la muestra, con 790.305 instalaciones al mes desde un repo congelado hace 905 días.
¿Cómo puede un repo estar activo pero el paquete seguir muerto?
Ese es codelucas/newspaper, y es lo más importante que encontró esta auditoría. Su rama por defecto tuvo un commit el 2026-07-21, días antes de la fecha de referencia, pero newspaper3k en PyPI publicó por última vez 0.2.8 el 2018-09-28 —hace 2.858 días— y aun así recibe 813.513 descargas al mes. Las comprobaciones a nivel de repositorio pasan; el artefacto que instalas tiene ocho años. Hay que revisar siempre la última fecha de publicación del registro por separado del historial de commits.
¿Los repos archivados solucionan esto? GitHub muestra una franja.
No de forma fiable, y @modelcontextprotocol/server-puppeteer explica por qué. Su campo repository en npm es null, así que no existe un enlace desde el paquete al repositorio archivado ni una franja que saltarse. Lo que sí entrega npm es la cadena deprecated del paquete —"Package no longer supported"— impresa en el momento de la instalación, y 127.232 instalaciones al mes siguen pasando por ahí. browserbase/mcp-server-browserbase anunció correctamente su cierre en su último commit; sus 20.389 instalaciones son en su mayoría anteriores a ese commit, así que dicen poco en un sentido u otro.
¿Cómo reviso mis propias dependencias rápidamente?
Empieza por la fecha del último commit en la rama por defecto, la fecha de publicación/subida en el registro, el campo deprecated de npm y la bandera archived del repositorio. Después verifica la atribución paquete-repositorio, inspecciona ramas no predeterminadas cuando la actividad diverja y usa gráficas de dependencias o lockfiles antes de llamar transitiva a una exposición. Choques de nombres como los proyectos sin relación wayback en Java y en PyPI hacen que esa escalada sea necesaria.


