Today, I will show this python script to check the certificate of url.
import sys
import ssl
import socket
from datetime import datetime
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from PyQt6.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QLabel,
QLineEdit, QPushButton, QTextEdit
)
def fetch_certificate_raw(hostname):
"""
Connects to the server and retrieves the certificate in DER format.
Also returns a validation status message.
"""
# Create a default SSL context (validates certificates)
context = ssl.create_default_context()
try:
# First attempt: strict validation
with socket.create_connection((hostname, 443), timeout=5) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
der_cert = ssock.getpeercert(binary_form=True)
return der_cert, "Certificate is VALID"
except ssl.SSLError as e:
# Certificate is invalid → try to retrieve it anyway
try:
unverified_context = ssl._create_unverified_context()
with socket.create_connection((hostname, 443), timeout=5) as sock:
with unverified_context.wrap_socket(sock, server_hostname=hostname) as ssock:
der_cert = ssock.getpeercert(binary_form=True)
return der_cert, f"Certificate is INVALID: {str(e)}"
except Exception:
return None, f"Could not retrieve certificate: {str(e)}"
except Exception as e:
return None, f"Connection error: {str(e)}"
def parse_certificate(der_cert):
"""
Converts a DER-encoded certificate into a cryptography.x509 object.
"""
return x509.load_der_x509_certificate(der_cert, default_backend())
class CertViewer(QWidget):
"""
Main GUI window for the HTTPS certificate viewer.
"""
def __init__(self):
super().__init__()
self.setWindowTitle("HTTPS Certificate Checker")
self.setGeometry(200, 200, 700, 600)
layout = QVBoxLayout()
# Input label + text field
layout.addWidget(QLabel("Enter URL (example: example.com):"))
self.input = QLineEdit()
layout.addWidget(self.input)
# Button to trigger certificate check
self.button = QPushButton("Check Certificate")
self.button.clicked.connect(self.check_certificate)
layout.addWidget(self.button)
# Output text box
self.output = QTextEdit()
self.output.setReadOnly(True)
layout.addWidget(self.output)
self.setLayout(layout)
def check_certificate(self):
"""
Triggered when the user presses the button.
Retrieves and displays certificate information.
"""
hostname = self.input.text().strip()
# Clean URL (remove http://, https://, and paths)
for prefix in ("https://", "http://"):
if hostname.startswith(prefix):
hostname = hostname[len(prefix):]
hostname = hostname.split("/")[0]
# Fetch certificate
der_cert, status = fetch_certificate_raw(hostname)
if der_cert is None:
self.output.setText(status)
return
# Parse certificate
cert = parse_certificate(der_cert)
# Build output text
text = f"=== CERTIFICATE STATUS ===\n{status}\n\n"
text += "=== CERTIFICATE DETAILS ===\n\n"
text += f"Subject:\n{cert.subject}\n\n"
text += f"Issuer:\n{cert.issuer}\n\n"
text += f"Serial Number: {cert.serial_number}\n\n"
text += f"Version: {cert.version}\n\n"
text += f"Valid From: {cert.not_valid_before}\n"
text += f"Valid To: {cert.not_valid_after}\n\n"
# Check expiration
if cert.not_valid_after < datetime.utcnow():
text += f"⚠ Certificate EXPIRED on: {cert.not_valid_after}\n\n"
# Subject Alternative Names (SAN)
try:
san = cert.extensions.get_extension_for_class(x509.SubjectAlternativeName)
text += f"Subject Alternative Names:\n{san.value}\n\n"
except Exception:
text += "Subject Alternative Names: (none)\n\n"
self.output.setText(text)
if __name__ == "__main__":
app = QApplication(sys.argv)
viewer = CertViewer()
viewer.show()
sys.exit(app.exec())