Pieza 2 de 64
TrámitePieza nº 0002 de 64

El precio va escrito en el botón

Quien va a pagar la tasa de extranjería (el NIE, la tarjeta de residencia, la prórroga de estancia) rellena el impreso en la sede de la Policía y marca su trámite. El precio no se lo dice el servidor, el ordenador de la Policía que le envía la página. Venía escrito en la propia página, en el botón que acaba de marcar, y la suma la hace su navegador.

Dominio
sede.policia.gob.es
Guardado
31 AGO 2026
Comprobado en vivo
15 SEP 2026
Citas
10 en 2 ficheros guardados
Lectura
unos 4 min
Captura de https://sede.policia.gob.es/
foto 1La portada de sede.policia.gob.es el 23 de septiembre de 2026: la sede electrónica de la Policía Nacional, con los accesos al DNI, al pasaporte y a los antecedentes policiales.Captura del 23 de septiembre de 2026, 10:07 (hora peninsular)

En la lista, cada trámite es una fila con su nombre y un botón redondo a la derecha. Una página web es un texto en HTML, hecho de etiquetas que le dicen al navegador qué pintar, y cada etiqueta lleva atributos, datos pegados a ella. En la etiqueta de ese botón está el precio, dos veces. Una en el atributo title, el globo de ayuda que sale al pasar el ratón por encima. Otra en un atributo que no existe en el estándar HTML y que se inventó para esto, con el número del trámite metido en el nombre. Los 28 precios viajan dentro de la página, a la vista de cualquiera que sepa mirar.

Captura de https://sede.policia.gob.es/Tasa790_012/ImpresoRellenar
foto 2El impreso de la tasa 790-012 el 23 de septiembre de 2026, sin rellenar y sin pulsar nada. Recuadrado, el botón del primer trámite: el que lleva el precio escrito en su etiqueta. En un aviso que queda más arriba, la propia página explica que el importe unitario se muestra al dejar el puntero encima del botón.Captura del 23 de septiembre de 2026, 14:16 (hora peninsular) · el recuadro es nuestro
1de 10sede.policia.gob.es/Tasa790_012/ImpresoRellenarlínea 303 de 646
Copia
archivo
Guardado
31 ago 2026
Peso
46,2 kB
sha256
03dcead6ef21…
301    </td>
302    <td>
303        <input id="tasa1Input" type="radio" name="tramiteSeleccionado" tasa1Importe="17.49" title="17.49 €" value="1" >
304    </td>
305</tr>
306<tr id="tasa2">
1El botón del primer trámite. El precio, dos veces: en el globo de ayuda y en un atributo inventado para la ocasión. Los otros 27 botones llevan el suyo igual.

El servidor los escribe ahí al generar la página. A partir de ese momento, la conversación sobre cuánto cuesta el trámite ocurre entre el navegador y el papel, sin volver a molestar a nadie. El programa busca el botón marcado y le pide el atributo cuyo nombre construye pegando «tasa», el número del trámite e «Importe». Con ese número hace las cuentas. Para los certificados lo multiplica por la cantidad pedida; para la prórroga de estancia le suma los días. Al final resta la cantidad complementaria, la casilla donde se declara lo ya ingresado.

2de 10sede.policia.gob.es/Tasa790_012/Scripts/impresoRellenarControlador.jslínea 372 de 1.402
Copia
archivo
Guardado
31 ago 2026
Peso
48,3 kB
sha256
79c3025587a8…
369tramiteSeleccionado=($("input[name='tramiteSeleccionado']:checked").val());
370//window.console && console.log("tramiteSeleccionado="+tramiteSeleccionado);
371//alert("tramiteSeleccionado="+tramiteSeleccionado);
372tramiteImporteUnitario=parseFloat($("input[name='tramiteSeleccionado']:checked").attr("tasa"+tramiteSeleccionado+"Importe"));
373//console.log("tramiteImporteUnitario="+tramiteImporteUnitario);
374//alert("tramiteImporteUnitario="+tramiteImporteUnitario);
375if (regularExpressionEnteroPositivoOCero.test($("#complementariaImporteEntero").val()) && regularExpressionDosCifras.test($("#complementariaImporteDecimal").val())){
2El navegador pregunta al botón marcado cuánto cuesta el trámite. El nombre del atributo se arma sobre la marcha con el número del trámite.
3de 10sede.policia.gob.es/Tasa790_012/Scripts/impresoRellenarControlador.jslínea 415 de 1.402sigue en el mismo fichero · 43 líneas más abajo
412else{
413    //console.log("tramiteImporteMultiplicadoPorCantidad="+tramiteImporteMultiplicadoPorCantidad);
414    //alert("tramiteImporteMultiplicadoPorCantidad="+tramiteImporteMultiplicadoPorCantidad);
415    importeFinal=(tramiteImporteMultiplicadoPorCantidad-complementariaImporte).toFixed(2);
416    //console.log("importeFinal="+importeFinal);
417    //alert("importeFinal="+importeFinal);
418}
3La cuenta final: lo que suma el trámite menos lo que se declara ya ingresado, a dos decimales.

El resultado se escribe en la casilla «Importe euros» del impreso, la que uno esperaría que rellenase la Administración. Si las comprobaciones del navegador han encontrado algún fallo, una fecha mal puesta o un trámite sin marcar, la casilla se queda vacía. Si no, recibe el número con sus dos decimales. Es el mismo número que, unos segundos después, viajará al servidor como importe a pagar.

4de 10sede.policia.gob.es/Tasa790_012/Scripts/impresoRellenarControlador.jslínea 423 de 1.402
Copia
archivo
Guardado
31 ago 2026
Peso
48,3 kB
sha256
79c3025587a8…
420}
421
422if (errores==""){
423    $("#total").val(importeFinal);
424    //console.log("errores vacio, importe final asignado="+importeFinal);
425    //alert("errores vacio, importe final asignado="+importeFinal);
426}else{
4Si no hay errores, el número entra en la casilla del importe. Si los hay, la casilla se vacía.
5de 10sede.policia.gob.es/Tasa790_012/ImpresoRellenarlínea 531 de 646
Copia
archivo
Guardado
31 ago 2026
Peso
46,2 kB
sha256
03dcead6ef21…
528        <input type="text" class="form-control text-right" placeholder=""
529               value=""
530               name="total" id="total"
531               maxlength="6" disabled>
532        <span class="input-group-addon">&euro;</span>
533    </div>
534</div>
5La casilla «Importe euros» tal como la manda el servidor: en gris, sin escribir, y con un máximo de seis caracteres.

La casilla llega desde el servidor con el atributo disabled: aparece en gris y no se puede escribir en ella. Un campo deshabilitado tampoco se envía con el formulario. Por eso, en el instante anterior al envío, el programa se lo quita, a esa casilla y a las otras dos zonas apagadas del impreso, y solo entonces manda el formulario. El importe que sale hacia el servidor es el que ha calculado el navegador.

6de 10sede.policia.gob.es/Tasa790_012/Scripts/impresoRellenarControlador.jslínea 115 de 1.402
Copia
archivo
Guardado
31 ago 2026
Peso
48,3 kB
sha256
79c3025587a8…
112if (formularioNewSubmit){
113    $('#fondo0').find('input').removeAttr('disabled');
114    $('#formapago').find('input').removeAttr('disabled');
115    $('#total').removeAttr('disabled');
116    var formulario = document.getElementById('f_conc');
117    formulario.submit();
118}
6Las cinco líneas del envío: se habilitan los campos apagados (el del importe entre ellos) y se manda el formulario.

Hay un trámite con precio variable: la prórroga de estancia de corta duración sin visado, 17,49 € de base más una cantidad por cada día. Esa cantidad por día también viaja en la página, en un campo de texto que vale 1.09 y que se esconde con una orden de estilo. Ocupa su sitio en el formulario, pero no se ve. Para leerlo, el programa toma el valor del campo escondido, le pega un punto y, detrás, el contenido de otra casilla: la de los decimales de la cantidad complementaria, que rellena quien presenta el impreso. Dos campos que no tienen nada que ver, unidos por un punto.

7de 10sede.policia.gob.es/Tasa790_012/ImpresoRellenarlínea 296 de 646
Copia
archivo
Guardado
31 ago 2026
Peso
46,2 kB
sha256
03dcead6ef21…
293<div class="alert " id="tasa1Info" hidden>
294    <b>Introduzca el número total de días de prórroga que va a solicitar y luego pulse el retorno de carro. (El importe por este trámite será: la tasa base correspondiente al trámite más el número de días solicitados multiplicado por la cantidad establecida p…
295        <input id="numeroDiasProrrogaEstanciaSinVisado" name="numeroDiasProrrogaEstanciaSinVisado" type="text" value="" style="text-align:right;width:6em "/>
296        <input id="tasa35Importe" type="text" name="tasa35Importe" style="visibility: hidden" value="1.09"/>
297    </b>
298</div>
7La casilla de los días de prórroga y, justo detrás, el precio de cada día escondido con visibility: hidden. Es un campo de texto normal, no un campo oculto.
8de 10sede.policia.gob.es/Tasa790_012/Scripts/impresoRellenarControlador.jslínea 384 de 1.402
Copia
archivo
Guardado
31 ago 2026
Peso
48,3 kB
sha256
79c3025587a8…
381if (tramiteSeleccionado=='1'){
382    if (regularExpressionNumeroCertificadosInformes.test($("#numeroDiasProrrogaEstanciaSinVisado").val())){
383        numeroDiasProrrogaEstanciaSinVisado = parseInt($("#numeroDiasProrrogaEstanciaSinVisado").val());
384        var importeDiarioTasa35 = parseFloat($("#tasa35Importe").val()+"."+$("#complementariaImporteDecimal").val());
385        tramiteImporteMultiplicadoPorCantidad = (tramiteImporteUnitario + (numeroDiasProrrogaEstanciaSinVisado * importeDiarioTasa35)).toFixed(2);
386
387    } else {
8El precio del día, formado con el valor de un campo y los decimales de otro que el ciudadano rellena para una cosa distinta.

Lo que sale de ahí es la cadena “1.09.” seguida de lo que el ciudadano haya escrito en esa otra casilla. Si escribió un 5, el programa tiene delante “1.09.5”, que no es un número. Entra entonces parseFloat, la orden que convierte texto en cifra. Lee de izquierda a derecha y, en cuanto encuentra algo que ya no puede ser parte del número, se detiene y devuelve lo que llevaba. Al llegar al segundo punto, para. Devuelve 1,09, el valor que había que leer.

Lo medimos en un Chrome 126 antes de escribirlo, porque esto no se deduce, se ejecuta. El importe que ve el ciudadano es correcto, y lo es por accidente. De dónde viene el desliz se ve nueve líneas más arriba. Allí está la misma expresión aplicada a los dos campos para los que se escribió, el entero y el decimal de la cantidad complementaria, que sí son dos mitades de un número. Alguien copió esa línea a un campo que ya traía el número entero. El resultado es correcto por la misma razón por la que un reloj parado da la hora dos veces al día.

9de 10sede.policia.gob.es/Tasa790_012/Scripts/impresoRellenarControlador.jslínea 376 de 1.402
Copia
archivo
Guardado
31 ago 2026
Peso
48,3 kB
sha256
79c3025587a8…
373//console.log("tramiteImporteUnitario="+tramiteImporteUnitario);
374//alert("tramiteImporteUnitario="+tramiteImporteUnitario);
375if (regularExpressionEnteroPositivoOCero.test($("#complementariaImporteEntero").val()) && regularExpressionDosCifras.test($("#complementariaImporteDecimal").val())){
376    complementariaImporte=parseFloat($("#complementariaImporteEntero").val()+"."+$("#complementariaImporteDecimal").val());
377    //console.log("complementariaImporte="+complementariaImporte);
378    //alert("complementariaImporte="+complementariaImporte);
379}
9La misma expresión nueve líneas antes, donde sí procede: aquí las dos casillas son el entero y los decimales del mismo número, y antes de juntarlas se comprueba que cada una sea un número.

El fichero conserva el taller a la vista. Hay 19 líneas de console.log y 15 de alert comentadas, las que se usaron para seguir las cuentas desde el navegador. Y hay cuatro bloques enteros con versiones anteriores del mismo código. Una copiaba en la casilla del total el globo de ayuda del botón, «17.49 €», y otra le quitaba los dos últimos caracteres para dejar el número. El precio siempre ha vivido en la página; lo que ha ido cambiando es de qué atributo se saca.

10de 10sede.policia.gob.es/Tasa790_012/Scripts/impresoRellenarControlador.jslínea 1190 de 1.402
Copia
archivo
Guardado
31 ago 2026
Peso
48,3 kB
sha256
79c3025587a8…
1187$("input[type=radio][name=tramiteSeleccionado]").click(
1188    function ()
1189    {
1190        //var importe=this.title.substring(0,this.title.length-2);
1191        //$("#total").val(importe);
1192        validarYCalcularImporteFinal(false);
1193    }
10Un comentario dentro de otro comentario: la versión que sacaba el precio del globo de ayuda quitándole los dos últimos caracteres, « €».

El impreso capturado el 31 de agosto de 2026 y el que sirve la sede el 15 de septiembre son el mismo fichero, byte a byte, y lo mismo vale para el programa que hace las cuentas. Qué hace el servidor con el importe que recibe, si lo vuelve a calcular por su cuenta antes de emitir el papel, no se ve desde fuera. Este museo no lo prueba. Lo que se ve es que el número sale del navegador de quien paga, y que ese navegador lo leyó del botón.

El impreso avisa de que la cantidad la asignará la Dependencia Policial. Hasta entonces, el precio va escrito en el botón y la suma la hace su navegador.

Lo que decimos
  • Los 28 precios de la tasa 790-012 están escritos en el HTML de la página, en atributos propios de cada botón.
  • El navegador los lee de ahí, multiplica, suma y resta, y escribe el resultado en la casilla del importe, que el servidor manda deshabilitada y el propio controlador habilita justo antes de enviar el formulario.
  • Para el precio por día de la prórroga, la expresión que lo lee junta el valor de un campo con los decimales de otro; medido en Chrome 126, el resultado sigue siendo 1,09 porque parseFloat se detiene en el segundo punto.
Lo que no decimos
  • No decimos que el servidor acepte sin más el importe que recibe: no lo hemos probado, no vamos a probarlo y desde fuera no se ve.
  • No decimos que nadie haya pagado de más ni de menos.
  • No decimos que la línea del importe diario cobre mal: hoy devuelve el número correcto.
  • Y no decimos nada sobre el impreso en papel que se descarga al final, que no hemos pedido.
Procedencia

De dónde sale cada cita

Cada trozo de código de esta ficha está en un fichero guardado tal como lo entregó el servidor, con su huella (sha256) y su hora. Las citas entre «» se comprueban por programa contra ese fichero antes de publicar.

Desgobierno Digital · https://desgobiernodigital.com/piezas/policia-precio-en-el-boton/ · copia impresa de la edición generada el 19 de octubre de 2026 · Un proyecto de BQuant · correcciones: @Gsnchez