<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nare Hate</title>
    <description>The latest articles on DEV Community by Nare Hate (@narehate78).</description>
    <link>https://dev.to/narehate78</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1858323%2Fd4433e35-c710-47dc-bf01-a805a55f959b.png</url>
      <title>DEV Community: Nare Hate</title>
      <link>https://dev.to/narehate78</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/narehate78"/>
    <language>en</language>
    <item>
      <title>Why the same face doesn't score 1.0 – lessons from building a face-similarity search in Python</title>
      <dc:creator>Nare Hate</dc:creator>
      <pubDate>Mon, 19 Oct 2026 15:37:56 +0000</pubDate>
      <link>https://dev.to/narehate78/why-the-same-face-doesnt-score-10-lessons-from-building-a-face-similarity-search-in-python-4ah3</link>
      <guid>https://dev.to/narehate78/why-the-same-face-doesnt-score-10-lessons-from-building-a-face-similarity-search-in-python-4ah3</guid>
      <description>&lt;p&gt;I built &lt;strong&gt;FaceMatch&lt;/strong&gt; as a portfolio project: you give it a photo, pick a face, and it ranks the followers or following of an Instagram profile by how similar their profile pictures (and optionally their recent posts) look to that face.&lt;/p&gt;

&lt;p&gt;Before anything else: &lt;strong&gt;a similarity score is not proof of identity.&lt;/strong&gt; The tool ranks visual similarity, nothing more. I'll come back to the privacy side at the end.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/Eight7Six/insta-facematch" rel="noopener noreferrer"&gt;github.com/Eight7Six/insta-facematch&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Detect all faces in the target image (RetinaFace, with MTCNN and OpenCV as fallbacks) and let the user click the one to search for.&lt;/li&gt;
&lt;li&gt;Compute a 512-dimensional embedding for that face with DeepFace (&lt;code&gt;Facenet512&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Log in via &lt;code&gt;instagrapi&lt;/code&gt; and load the followers/following of one or more profiles.&lt;/li&gt;
&lt;li&gt;For every account, download the profile picture and optionally the last &lt;em&gt;N&lt;/em&gt; posts, compute embeddings for every face found, and keep the best cosine similarity.&lt;/li&gt;
&lt;li&gt;Print a ranking, a report of accounts that could not be compared (with a reason), and export both to CSV.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The comparison itself is tiny:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cosine_similarity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linalg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;1e-9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linalg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;1e-9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything around it is where the interesting problems were.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 1: "No matching distribution" usually means "wrong Python"
&lt;/h2&gt;

&lt;p&gt;When I tested a clean install on a second machine, &lt;code&gt;pip install -r requirements.txt&lt;/code&gt; failed with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ERROR: Could not find a version that satisfies the requirement tensorflow==2.21.0 (from versions: 2.22.0rc0)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The hint is in the parentheses: pip saw exactly one TensorFlow version. TensorFlow ships pre-built wheels per Python version, and 2.21.0 only has them for Python 3.10–3.13. The second machine had the latest Python, 3.14, and the only release with 3.14 wheels was a release candidate.&lt;/p&gt;

&lt;p&gt;The fix was not in the code but in the docs: the README now states the supported Python versions up front and tells users to create the virtual environment with an explicit version (&lt;code&gt;py -3.13 -m venv .venv&lt;/code&gt;) instead of a plain &lt;code&gt;python -m venv&lt;/code&gt;, which silently picks whatever the default is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 2: The same person doesn't score anywhere near 1.0
&lt;/h2&gt;

&lt;p&gt;My test target was a public, verified account. I expected a score close to 1. I got around &lt;strong&gt;0.5&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's normal. A score of 1.0 only happens for identical images. For Facenet512, DeepFace's own &lt;code&gt;verify()&lt;/code&gt; threshold is a cosine &lt;em&gt;distance&lt;/em&gt; of 0.30, i.e. a similarity of &lt;strong&gt;0.70&lt;/strong&gt;, and that is tuned on good, frontal image pairs. In my case several things pulled the score down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The target face was tiny.&lt;/strong&gt; My target was a screenshot about 480 px wide; the face was maybe 40–50 px. Facenet512 works on 160×160 inputs, so the face got upscaled three to four times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pose, expression and lighting.&lt;/strong&gt; A serious portrait compares badly to a broad smile under stadium lights.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only one post was actually compared&lt;/strong&gt; – more on that in Lesson 4.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I kept the default threshold at 0.55 on purpose: it is below DeepFace's 0.70 and acts as a generous pre-filter for manual review, not as a decision.&lt;/p&gt;

&lt;p&gt;There's also a statistical trap: the tool keeps the &lt;em&gt;best&lt;/em&gt; score per account across all faces in all images. With hundreds of accounts and several images each, you make thousands of comparisons, and some stranger will land above the threshold by chance. More images do not automatically mean better results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 3: Follower lists only give you thumbnails
&lt;/h2&gt;

&lt;p&gt;The profile picture URLs in follower lists point to &lt;strong&gt;150×150 px&lt;/strong&gt; images – you can see &lt;code&gt;s150x150&lt;/code&gt; in the URL. My first idea was to edit that part of the URL. That doesn't work: Instagram's CDN URLs are signed, and a modified URL is rejected.&lt;/p&gt;

&lt;p&gt;The full-size picture needs one extra profile request per account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;details&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;profile_pic_url_hd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;profile_pic_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;profile_pic_url_hd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;is_private&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_private&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two side effects: the run gets a bit slower (one more request per account), and the "private" flag becomes reliable, because the follower list often doesn't populate it at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 4: Skipping carousels skipped the best match
&lt;/h2&gt;

&lt;p&gt;Originally the code only evaluated single-photo posts and skipped everything else. With "3 posts per account", my test account's last three posts were a reel, a photo and a carousel – so only &lt;em&gt;one&lt;/em&gt; post was compared.&lt;/p&gt;

&lt;p&gt;After adding carousels (using only the first photo of each), the score for the same account went from about 0.5 to &lt;strong&gt;0.60&lt;/strong&gt;. That first carousel photo came from the same match as the target image: same jersey, same lighting, same broad smile.&lt;/p&gt;

&lt;p&gt;I deliberately use only the first photo. A carousel can hold up to 20 images; evaluating all of them would multiply the runtime and – see Lesson 2 – the number of chance matches. Reels stay skipped: their cover frames are often blurry or covered with text.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 5: Detect once, or your indices drift apart
&lt;/h2&gt;

&lt;p&gt;The log showed this on every run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Detector retinaface: 7 face(s) found in Target.png
Detector retinaface: 6 face(s) found.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same image, same detector, different counts. The program detected faces twice: once with &lt;code&gt;DeepFace.represent(align=True)&lt;/code&gt; for the embeddings, and once with &lt;code&gt;DeepFace.extract_faces(align=False)&lt;/code&gt; to draw the boxes in the selection window. With &lt;code&gt;align=True&lt;/code&gt;, DeepFace pads the image with a black border before detection, so the detector sees a slightly different picture, and borderline faces flip in or out.&lt;/p&gt;

&lt;p&gt;A click was mapped back to the right embedding via bounding-box overlap, so the result was correct. But the numbers in the window referred to a list of six faces, while the &lt;code&gt;--person-index&lt;/code&gt; CLI option referred to a list of seven. The second detection also cost about ten seconds.&lt;/p&gt;

&lt;p&gt;The fix: detect once and pass those faces to the picker. One list, one numbering, and the overlap-matching code could be deleted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 6: A &lt;code&gt;continue&lt;/code&gt; that skipped the cleanup
&lt;/h2&gt;

&lt;p&gt;Downloaded images are supposed to be deleted right after analysis. Images without a detectable face stayed on disk anyway:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;faces&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_embeddings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DETECTOR_ORDER&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;faces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;continue&lt;/span&gt;                      &lt;span class="c1"&gt;# jumps past the cleanup below
&lt;/span&gt;&lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;img_path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unlink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;missing_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;try/finally&lt;/code&gt; fixes it and also covers exceptions during analysis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;faces&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_embeddings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DETECTOR_ORDER&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;img_path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unlink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;missing_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;faces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I had first documented this as a "known issue". Fixing it took three lines – a good reminder that a known issue in a README is sometimes just a bug you haven't fixed yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy and responsible use
&lt;/h2&gt;

&lt;p&gt;This is the part I thought about most:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Similarity is not identity.&lt;/strong&gt; Every "possible match" is an unverified hypothesis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Face embeddings are biometric data.&lt;/strong&gt; Under the GDPR and similar laws, processing them for third parties generally needs a legal basis. Running a tool like this against real people without their consent may be unlawful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instagram's Terms of Use restrict automated access.&lt;/strong&gt; &lt;code&gt;instagrapi&lt;/code&gt; uses Instagram's undocumented mobile API, so use a throwaway account you are prepared to lose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The demo only uses public figures.&lt;/strong&gt; For testing, I created a separate account that follows ten verified public accounts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The README states all of this up front, and the repository ignores session files, target images, downloaded pictures and result CSVs by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;The actual face comparison is three lines of NumPy. The real work was everything around it: packaging and Python versions, data quality, API quirks, consistent state between GUI and CLI, cleanup, and documentation that's honest about the limits.&lt;/p&gt;

&lt;p&gt;Feedback on the code – and on the ethics – is welcome: &lt;a href="https://github.com/Eight7Six/insta-facematch" rel="noopener noreferrer"&gt;github.com/Eight7Six/insta-facematch&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>computervision</category>
      <category>machinelearning</category>
      <category>privacy</category>
    </item>
    <item>
      <title>Best of Self-Sovereign Identity: Digitalcourage, World Passport and Memdeklaro</title>
      <dc:creator>Nare Hate</dc:creator>
      <pubDate>Thu, 25 Dec 2025 18:32:32 +0000</pubDate>
      <link>https://dev.to/narehate78/vat-helpline-vs-ad-hoc-vat-advisory-which-is-more-effective-for-uk-businesses-dealing-with-151k</link>
      <guid>https://dev.to/narehate78/vat-helpline-vs-ad-hoc-vat-advisory-which-is-more-effective-for-uk-businesses-dealing-with-151k</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Febfsfk8kqfwpsy5knul8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Febfsfk8kqfwpsy5knul8.jpg" alt="Memdeklaro vs. Digitalcourage vs. World Passport" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Self-sovereign identity empowers individuals to take control of their personal information, reducing unnecessary data collection and strengthening privacy in daily interactions. Similarly, non-government ID cards give people a portable way to state who they are without relying on a national identity card, passport or other government-issued credential, supporting independence from centralized identity systems.&lt;/p&gt;

&lt;p&gt;The three products compared here - &lt;strong&gt;Memdeklaro&lt;/strong&gt;, &lt;strong&gt;Digitalcourage Lichtbildausweis&lt;/strong&gt;, and the &lt;strong&gt;World Passport&lt;/strong&gt; - offer effective, modern solutions for self-sovereign identity in 2026 and beyond.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Memdeklaro&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Digitalcourage Lichtbildausweis&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;World Passport&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Basic concept&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Self-declared identity document&lt;/td&gt;
&lt;td&gt;Personalized, non-official photo ID&lt;/td&gt;
&lt;td&gt;Non-government passport based on world citizenship&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Year of launch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2024&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2012&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1954&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Issued by&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No central issuer; generated by the individual&lt;/td&gt;
&lt;td&gt;Digitalcourage e.V.&lt;/td&gt;
&lt;td&gt;World Service Authority (WSA)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;€15 per card, plus shipping&lt;/td&gt;
&lt;td&gt;$75 / $100 / $125 for 3 / 5 / 10 years&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Format&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Physical or digital card&lt;/td&gt;
&lt;td&gt;Physical card&lt;/td&gt;
&lt;td&gt;Passport booklet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;What data is included on the ID?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;First name, last name, photo, birth date, signature, notes field&lt;/td&gt;
&lt;td&gt;First name, last name, photo, birth date, birth place, citizenship or stateless status, eye color, height, home address, pseudonym&lt;/td&gt;
&lt;td&gt;First name, last name, photo, birth date, birth place&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;What data is excluded from the ID?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Birth place, citizenship or stateless status, parents' names&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Citizenship or stateless status&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Government-issued?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Requires an existing government ID?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;No&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;No&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;No&lt;/strong&gt;; requires fingerprints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Centralized database&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;No&lt;/strong&gt;; generation occurs locally in the browser&lt;/td&gt;
&lt;td&gt;Data is deleted after 10 days&lt;/td&gt;
&lt;td&gt;Issuer maintains a registration system&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Open source&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes; public-domain project&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Proprietary&lt;/td&gt;
&lt;td&gt;Proprietary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Main philosophy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Radical individual self-determination&lt;/td&gt;
&lt;td&gt;Privacy, data minimization and experimentation with non-official IDs&lt;/td&gt;
&lt;td&gt;World citizenship, freedom of movement and human rights&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A free, open-source self-declaration that lets individuals create their own non-government identity document.&lt;/td&gt;
&lt;td&gt;A privacy-oriented, non-official photo ID allowing users to decide which information appears on the card.&lt;/td&gt;
&lt;td&gt;A passport-style document representing world citizenship and intended as a symbol and potential tool for freedom of movement.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  1. Memdeklaro: the strongest form of self-declaration
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqe57oqa44550lqu0gfy4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqe57oqa44550lqu0gfy4.jpg" alt="Memdeklaro" width="470" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Memdeklaro is an open source non-government identity solution which allows people to generate and print an identity declaration for free. The generator runs locally in the user's browser, and the site explicitly says that the data is not sent anywhere. The resulting document can be printed as a business card or CR-80 card, or used digitally. &lt;/p&gt;

&lt;p&gt;The ID contains a self-chosen name, birth date, photograph, signature and notes field. It explicitly does not include birth place, citizenship or stateless status, or birth parents' names.&lt;/p&gt;

&lt;p&gt;It can be used as a physical or digital ID card wherever a non-government ID is accepted.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Digitalcourage Lichtbildausweis: privacy by design
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw8ej2fzwabbkrde53urz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw8ej2fzwabbkrde53urz.jpg" alt="Digitalcourage" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Digitalcourage sells a personalized physical photo ID for €15 in their online store. After ordering, the customer receives a link to an input form where they enter their desired information and upload a photograph. Digitalcourage then manufactures and mails the card.&lt;/p&gt;

&lt;p&gt;The issuer allows users to select the information they are willing to disclose, and says that the information supplied for production is deleted after ten days. Its privacy policy also specifically notes that the information used to produce the card can be either fictional or real.&lt;/p&gt;

&lt;p&gt;Digitalcourage says that it can be used wherever a non-official photo ID is accepted.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. World Passport: the established alternative
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq2hwmg8dk9l9f5xj3mg4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq2hwmg8dk9l9f5xj3mg4.jpg" alt="World Passport" width="450" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The World Passport is part of a much larger philosophical project: the World Citizen Government (WCG), founded by Garry Davis in 1953. Its administrative branch, the World Service Authority (WSA), issues the World Passport and other world citizenship documents.&lt;/p&gt;

&lt;p&gt;It is a 30-page Machine Readable Travel Document containing a machine-readable code line, photograph and ghost image, security paper, laminated data page and hologram. It is printed in seven languages: English, French, Spanish, Russian, Arabic, Chinese and Esperanto. It also contains visa pages and space for additional information.&lt;/p&gt;

&lt;p&gt;The World Passport is intended to represent &lt;strong&gt;world citizenship and the individual's right to freedom of movement&lt;/strong&gt;. WCG explicitly says that the passport does not state the bearer's nationality, only their birthplace.&lt;/p&gt;

&lt;p&gt;WCG says that the World Passport has been accepted on a case-by-case basis by more than 185 countries. Its recognition page, updated in February 2026, provides examples and distinguishes between "de facto" recognition and countries that WCG describes as having given "de jure" recognition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In everyday language, all three can reasonably be described as &lt;strong&gt;non-government identity alternatives&lt;/strong&gt; or &lt;strong&gt;self-asserted identity documents&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;These products ultimately represent three different approaches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memdeklaro&lt;/strong&gt; says: &lt;em&gt;I define myself.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Digitalcourage&lt;/strong&gt; says: &lt;em&gt;I decide what information about myself I disclose.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The World Passport&lt;/strong&gt; says: &lt;em&gt;My identity need not be tied to a nation-state.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Best for maximum individual autonomy: Memdeklaro
&lt;/h3&gt;

&lt;p&gt;Memdeklaro is the clearest expression of the proposition that &lt;strong&gt;identity can be declared by the individual rather than a centralized institution&lt;/strong&gt;. It is free, open source, locally generated and explicitly designed without a central database or third-party identity authority.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best for a privacy-oriented ID card: Digitalcourage
&lt;/h3&gt;

&lt;p&gt;Digitalcourage occupies the pragmatic middle ground. It provides a professionally manufactured physical card while allowing the user to choose the information printed on it. It is therefore particularly suited to situations where a person wants a &lt;strong&gt;photo-bearing, non-official identity card&lt;/strong&gt; without presenting a conventional government document.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best for an alternative passport/world citizenship document: World Passport
&lt;/h3&gt;

&lt;p&gt;The World Passport has a much longer institutional history, a passport-style physical format, machine-readable features and a stated history of case-by-case recognition by authorities around the world.&lt;/p&gt;

&lt;h2&gt;
  
  
  What do you think?
&lt;/h2&gt;

&lt;p&gt;Do you know any more self-sovereign identity projects? Write a comment below!&lt;/p&gt;

</description>
      <category>startup</category>
      <category>ai</category>
      <category>web3</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
