-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.html
More file actions
777 lines (693 loc) · 206 KB
/
install.html
File metadata and controls
777 lines (693 loc) · 206 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="keywords" content="Osint,CTF,Investigation">
<meta name="author" content="gl0bal01">
<title>Bookmarklets - Easy Installation - gl0bal01</title>
<meta name="description" content="Install powerful JavaScript bookmarklets for web development, productivity, and more">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
line-height: 1.6;
color: #2c3e50;
background: #f8fafc;
min-height: 100vh;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 40px 20px;
}
header {
text-align: center;
margin-bottom: 60px;
padding: 40px 0;
background: white;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
}
h1 {
font-size: 2.5rem;
margin-bottom: 12px;
color: #1a202c;
font-weight: 700;
}
.subtitle {
font-size: 1.1rem;
color: #64748b;
font-weight: 400;
}
.installation-guide {
background: white;
border-radius: 12px;
padding: 40px;
margin-bottom: 40px;
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
border: 1px solid #e2e8f0;
}
.installation-guide h2 {
color: #1a202c;
margin-bottom: 20px;
font-size: 1.5rem;
font-weight: 600;
}
.installation-guide > p {
color: #64748b;
margin-bottom: 30px;
font-size: 1rem;
}
.browser-instructions {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 24px;
}
.browser-card {
background: #f1f5f9;
border-radius: 8px;
padding: 24px;
border: 1px solid #ddd;
}
.browser-card h3 {
color: #3b82f6;
margin-bottom: 16px;
font-size: 1.1rem;
font-weight: 600;
}
.browser-card ol {
color: #475569;
padding-left: 20px;
}
.browser-card li {
margin-bottom: 8px;
font-size: 0.9rem;
}
.search-box {
background: white;
border-radius: 12px;
padding: 30px;
margin-bottom: 40px;
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
border: 1px solid #e2e8f0;
}
#search {
width: 100%;
padding: 16px 20px;
border: 2px solid #e2e8f0;
border-radius: 8px;
font-size: 1rem;
transition: all 0.2s ease;
background: #f8fafc;
}
#search:focus {
outline: none;
border-color: #3b82f6;
background: white;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
.categories {
display: grid;
grid-template-columns: 1fr;
gap: 40px;
}
.category {
background: white;
border-radius: 12px;
padding: 32px;
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
border: 1px solid #e2e8f0;
transition: all 0.3s ease;
}
.category:hover {
transform: translateY(-2px);
box-shadow: 0 4px 20px rgba(0,0,0,0.12);
}
.category h2 {
color: #1a202c;
margin-bottom: 8px;
font-size: 1.4rem;
font-weight: 600;
display: flex;
align-items: center;
}
.category > p {
color: #64748b;
margin-bottom: 32px;
font-size: 0.95rem;
}
.category-icon {
font-size: 1.5rem;
margin-right: 12px;
}
.bookmarklet {
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 24px;
margin-bottom: 20px;
transition: all 0.2s ease;
background: #fafbfc;
}
.bookmarklet:hover {
border-color: #3b82f6;
background: white;
box-shadow: 0 2px 8px rgba(59, 130, 246, 0.1);
}
.bookmarklet:last-child {
margin-bottom: 0;
}
.bookmarklet-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 12px;
gap: 16px;
}
.bookmarklet-title {
font-size: 1.1rem;
font-weight: 600;
color: #1a202c;
flex: 1;
}
.button-group {
display: flex;
gap: 8px;
flex-shrink: 0;
}
.bookmarklet-link {
background: #3b82f6;
color: white;
text-decoration: none;
border-radius: 6px;
padding: 10px 16px;
font-size: 0.9rem;
font-weight: 500;
transition: all 0.2s ease;
cursor: grab;
border: none;
white-space: nowrap;
display: inline-block;
}
.bookmarklet-link:hover {
background: #2563eb;
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(37, 99, 235, 0.3);
}
.bookmarklet-link:active {
cursor: grabbing;
transform: translateY(0);
}
.copy-btn {
background: #10b981;
color: white;
border: none;
border-radius: 6px;
padding: 10px 16px;
font-size: 0.9rem;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
white-space: nowrap;
}
.copy-btn:hover {
background: #059669;
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(16, 185, 129, 0.3);
}
.bookmarklet-description {
color: #64748b;
margin-bottom: 16px;
font-size: 0.95rem;
line-height: 1.5;
}
.features {
list-style: none;
padding: 0;
}
.features li {
padding: 4px 0;
color: #475569;
font-size: 0.9rem;
display: flex;
align-items: center;
}
.features li::before {
content: "✓";
color: #10b981;
margin-right: 10px;
font-weight: 600;
font-size: 0.9rem;
}
.drag-instruction {
background: #eff6ff;
border: 1px solid #bfdbfe;
border-radius: 8px;
padding: 16px;
margin-bottom: 32px;
color: #1e40af;
font-size: 0.9rem;
text-align: center;
}
.drag-instruction strong {
color: #1d4ed8;
}
.notification {
position: fixed;
top: 20px;
right: 20px;
background: #10b981;
color: white;
padding: 15px 20px;
border-radius: 10px;
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
z-index: 1000;
display: none;
animation: slideIn 0.3s ease-out;
}
.notification.error {
background: #ef4444;
}
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@media (max-width: 768px) {
.container {
padding: 20px 16px;
}
h1 {
font-size: 2rem;
}
.browser-instructions {
grid-template-columns: 1fr;
}
.bookmarklet-header {
flex-direction: column;
align-items: stretch;
gap: 12px;
}
.button-group {
justify-content: center;
}
}
@media (max-width: 480px) {
.installation-guide,
.search-box,
.category {
padding: 24px;
}
.browser-card {
padding: 20px;
}
.button-group {
flex-direction: column;
gap: 8px;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>🔖 Osint/CTFs Bookmarklets</h1>
<p class="subtitle">The trouble is, you think you have time.</p>
</header>
<div class="installation-guide">
<h2>📚 How to Install Bookmarklets</h2>
<p>Bookmarklets are small JavaScript programs that run when you click a bookmark. Simply drag the buttons below to your bookmark bar to install them.</p>
<div class="drag-instruction">
<strong>💡 Quick Install:</strong> Drag any blue button directly to your browser's bookmark bar to install it instantly! Alternatively, click "Copy Code" to get the JavaScript code for manual installation.
</div>
<div class="browser-instructions">
<div class="browser-card">
<h3>🌐 Chrome / Edge</h3>
<ol>
<li>Make sure your bookmark bar is visible (Ctrl+Shift+B)</li>
<li>Drag the blue button to your bookmark bar</li>
<li>The bookmarklet is now ready to use</li>
<li>Click it on any website to activate</li>
</ol>
</div>
<div class="browser-card">
<h3>🦊 Firefox</h3>
<ol>
<li>Show your bookmarks toolbar (Ctrl+Shift+B)</li>
<li>Drag the blue button to the toolbar</li>
<li>The bookmarklet will be automatically installed</li>
<li>Click to run on any webpage</li>
</ol>
</div>
<div class="browser-card">
<h3>🧭 Safari</h3>
<ol>
<li>Show the bookmarks bar (View → Show Favorites Bar)</li>
<li>Drag the blue button to the bar</li>
<li>Safari will automatically create the bookmark</li>
<li>Click to execute on any site</li>
</ol>
</div>
</div>
</div>
<div class="search-box">
<input type="text" id="search" placeholder="🔍 Search bookmarklets...">
</div>
<div class="categories" id="categories">
<div class="category" data-category="osint">
<h2><span class="category-icon">🔍</span>OSINT Tools</h2>
<p>Essential tools for open-source intelligence gathering and web research</p>
<div class="bookmarklet">
<div class="bookmarklet-header">
<div class="bookmarklet-title">🔍 Expose Hidden Content</div>
<div class="button-group">
<a href="javascript:void(0)"
class="bookmarklet-link"
draggable="true"
data-bookmarklet-name="Expose Hidden Content"
data-bookmarklet-code="javascript:(function(){const s=document.createElement('style');s.textContent=".exposed-comment{background-color:yellow!important;color:black!important;padding:5px!important;border:2px solid red!important;display:block!important;margin:5px 0!important;font-family:monospace!important;white-space:pre-wrap!important;position:relative!important;z-index:9999!important;}.exposed-hidden{background-color:#ffccff!important;color:black!important;padding:5px!important;border:2px solid blue!important;display:block!important;visibility:visible!important;opacity:1!important;margin:5px 0!important;font-family:monospace!important;position:relative!important;z-index:9999!important;}.tag-name{background-color:#333!important;color:white!important;padding:2px 4px!important;border-radius:3px!important;font-weight:bold!important;margin-right:5px!important;}";document.head.appendChild(s);const cC=document.createElement('div');cC.id='exposed-comments-container';cC.style.cssText='position:relative;z-index:9998;margin-bottom:20px;';document.body.insertBefore(cC,document.body.firstChild);const hC=document.createElement('div');hC.id='exposed-hidden-container';hC.style.cssText='position:relative;z-index:9998;margin-top:20px;';document.body.insertBefore(hC,cC.nextSibling);(function(){const fC=n=>{const cs=[],w=document.createTreeWalker(n,NodeFilter.SHOW_COMMENT,null,false);let com;while(com=w.nextNode()){cs.push(com);}return cs;};const cs=fC(document.documentElement);cs.forEach(com=>{const w=document.createElement('div');w.className='exposed-comment';w.innerHTML='<span class="tag-name">COMMENT</span>&lt;!-- '+com.textContent+' --&gt;';cC.appendChild(w);});})();(function(){const sel=['[style*="display: none"]','[style*="display:none"]','[hidden]','[style*="visibility: hidden"]','[style*="visibility:hidden"]','[style*="opacity: 0"]','[style*="opacity:0"]','script','noscript','template','meta','link','style'];const hes=document.querySelectorAll(sel.join(','));hes.forEach(el=>{const w=document.createElement('div');w.className='exposed-hidden';const tn=document.createElement('span');tn.className='tag-name';tn.textContent=el.tagName;w.appendChild(tn);const c=document.createElement('div');c.textContent=(el.tagName==='SCRIPT'||el.tagName==='STYLE')?el.textContent:el.outerHTML;w.appendChild(c);hC.appendChild(w);});})();const ctrl=document.createElement('div');ctrl.style.cssText="position:fixed;top:10px;right:10px;z-index:10000;background:#333;color:white;padding:5px;border-radius:5px;font-family:sans-serif;";ctrl.innerHTML="<p>Comments & Hidden Tags Exposed</p><button id='toggle-exposed'>Hide</button><button id='remove-exposed'>Remove</button>";document.body.appendChild(ctrl);document.getElementById('toggle-exposed').addEventListener('click',function(){const items=document.querySelectorAll('.exposed-comment, .exposed-hidden');items.forEach(el=>el.style.display=el.style.display==='none'?'block':'none');this.textContent=this.textContent==='Hide'?'Show':'Hide';});document.getElementById('remove-exposed').addEventListener('click',function(){const items=document.querySelectorAll('.exposed-comment, .exposed-hidden');items.forEach(el=>el.remove());ctrl.remove();});})();"
title="Drag this button to your bookmarks bar">
Expose Hidden
</a>
<button class="copy-btn" onclick="copyBookmarkletCode(this)">Copy Code</button>
</div>
</div>
<div class="bookmarklet-description">
Reveals hidden HTML comments and concealed elements on any webpage for thorough content analysis.
</div>
<ul class="features">
<li>Exposes HTML comments with visual highlighting</li>
<li>Shows hidden elements and scripts</li>
<li>Color-coded display for easy identification</li>
<li>Interactive control panel with toggle options</li>
<li>Non-destructive analysis tool</li>
</ul>
</div>
<div class="bookmarklet">
<div class="bookmarklet-header">
<div class="bookmarklet-title">🔗 URLs Extractor</div>
<div class="button-group">
<a href="javascript:void(0)"
class="bookmarklet-link"
draggable="true"
data-bookmarklet-name="URLs Extractor"
title="Drag this button to your bookmarks bar"
data-bookmarklet-code="javascript:(function(){for(var a=location.hostname,b=document.title||a,c=new Date,d=c.getFullYear()+"-"+(c.getMonth()+1+"").padStart(2,"0")+"-"+(c.getDate()+"").padStart(2,"0"),f=(c.getHours()+"").padStart(2,"0")+":"+(c.getMinutes()+"").padStart(2,"0"),g=document.querySelectorAll("*"),h=[],k=new Set,l=0;l<g.length;l++){var m=g[l],e=null,n=null;if(m.src&&!k.has(m.src)){if(e="object"==typeof m.src&&void 0!==m.src.animVal?m.src.animVal+"":"object"==typeof m.src&&void 0!==m.src.baseVal?m.src.baseVal+"":m.src+"",!e||""===e||"null"===e||"undefined"===e)continue;n=(m.alt||m.title||m.getAttribute("aria-label")||"Resource")+"",k.add(e),h.push({url:e,title:n,type:"Resource"})}if(m.href&&!k.has(m.href)){if(e="object"==typeof m.href&&void 0!==m.href.animVal?m.href.animVal+"":"object"==typeof m.href&&void 0!==m.href.baseVal?m.href.baseVal+"":m.href+"",!e||""===e||"null"===e||"undefined"===e)continue;n="",n=m.textContent&&m.textContent.trim()?(m.textContent+"").trim():m.title?m.title+"":m.getAttribute("aria-label")?m.getAttribute("aria-label")+"":m.alt?m.alt+"":"A"===m.tagName?"Link":"Link ("+m.tagName.toLowerCase()+")",100<n.length&&(n=n.substring(0,97)+"..."),n&&""!==n.trim()&&"[object SVGAnimatedString]"!==n||(n="Link ("+m.tagName.toLowerCase()+")"),k.add(e),h.push({url:e,title:n,type:"Link"})}}h.sort(function(c,a){if(c.type!==a.type){if("Link"===c.type)return-1;if("Link"===a.type)return 1}return c.url<a.url?-1:c.url>a.url?1:0});var o="================================================================================\n";o+=" URL EXTRACTION REPORT\n",o+="================================================================================\n\n",o+="Page Title: "+b+"\n",o+="Site: "+a+"\n",o+="URL: "+location.href+"\n",o+="Extraction Date: "+d+" at "+f+"\n",o+="Total URLs Found: "+h.length+"\n",o+="Links: "+h.filter(function(a){return"Link"===a.type}).length+"\n",o+="Resources: "+h.filter(function(a){return"Resource"===a.type}).length+"\n",o+="\n================================================================================\n",o+=" EXTRACTED URLS\n",o+="================================================================================\n\n";for(var p,q=0;q<h.length;q++)p=h[q],o+="["+p.type+"] "+p.title+"\n",o+=p.url+"\n\n";var r="<!DOCTYPE html>\n<html>\n<head>\n";r+="<meta charset='UTF-8'>\n",r+="<title>URL Report - "+b+"</title>\n",r+="<style>\n",r+="body { font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }\n",r+=".container { max-width: 900px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }\n",r+=".header { background: #2c3e50; color: white; padding: 20px; margin: -20px -20px 20px -20px; border-radius: 8px 8px 0 0; }\n",r+=".stats { background: #ecf0f1; padding: 15px; border-radius: 5px; margin: 20px 0; }\n",r+=".stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }\n",r+=".stat-item { text-align: center; }\n",r+=".stat-number { font-size: 24px; font-weight: bold; color: #2980b9; }\n",r+=".stat-label { font-size: 12px; color: #7f8c8d; }\n",r+=".url-item { margin: 15px 0; padding: 15px; background: #f8f9fa; border-left: 4px solid #3498db; border-radius: 0 5px 5px 0; }\n",r+=".url-item.resource { border-left-color: #e74c3c; }\n",r+=".url-title { font-weight: bold; color: #2c3e50; margin-bottom: 5px; }\n",r+=".url-link { color: #3498db; text-decoration: none; word-break: break-all; }\n",r+=".url-link:hover { text-decoration: underline; }\n",r+=".url-type { display: inline-block; padding: 2px 8px; border-radius: 3px; font-size: 11px; font-weight: bold; color: white; margin-bottom: 5px; }\n",r+=".type-link { background: #3498db; }\n",r+=".type-resource { background: #e74c3c; }\n",r+=".search-box { width: 100%; padding: 10px; margin: 20px 0; border: 1px solid #ddd; border-radius: 5px; font-size: 14px; }\n",r+=".back-to-top { position: fixed; bottom: 20px; right: 20px; background: #3498db; color: white; padding: 10px 15px; border-radius: 5px; text-decoration: none; }\n",r+="</style>\n</head>\n<body>\n",r+="<div class='container'>\n",r+="<div class='header'>\n",r+="<h1>🔗 URL Extraction Report</h1>\n",r+="<p><strong>Page:</strong> "+b+"</p>\n",r+="<p><strong>Site:</strong> "+a+"</p>\n",r+="<p><strong>Source:</strong> <a href='"+location.href+"' style='color: #ecf0f1;'>"+location.href+"</a></p>\n",r+="<p><strong>Extracted:</strong> "+d+" at "+f+"</p>\n",r+="</div>\n",r+="<div class='stats'>\n",r+="<div class='stats-grid'>\n",r+="<div class='stat-item'><div class='stat-number'>"+h.length+"</div><div class='stat-label'>Total URLs</div></div>\n",r+="<div class='stat-item'><div class='stat-number'>"+h.filter(function(a){return"Link"===a.type}).length+"</div><div class='stat-label'><a href='#links-section' style='color: inherit; text-decoration: none;'>Links</a></div></div>\n",r+="<div class='stat-item'><div class='stat-number'>"+h.filter(function(a){return"Resource"===a.type}).length+"</div><div class='stat-label'><a href='#resources-section' style='color: inherit; text-decoration: none;'>Resources</a></div></div>\n",r+="</div>\n</div>\n",r+="<input type='text' class='search-box' placeholder='🔍 Search URLs...' onkeyup='filterUrls(this.value)'>\n",r+="<div id='urlList'>\n";for(var p,s="",q=0;q<h.length;q++){p=h[q],p.type!==s&&(r+="Link"===p.type?"<h2 id='links-section' style='color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 10px; margin-top: 30px;'>🔗 Links ("+h.filter(function(a){return"Link"===a.type}).length+")</h2>\n":"<h2 id='resources-section' style='color: #2c3e50; border-bottom: 2px solid #e74c3c; padding-bottom: 10px; margin-top: 30px;'>📁 Resources ("+h.filter(function(a){return"Resource"===a.type}).length+")</h2>\n",s=p.type);var t=p.type.toLowerCase(),u=(p.url||"")+"",v=(p.title||"")+"",w="",x=!1;if(u.startsWith("data:")&&u.includes("base64,"))try{var y=u.substring(5,u.indexOf(";")),z=u.split("base64,")[1];y.startsWith("image/")?x=!0:z&&(w=atob(z),200<w.length&&(w=w.substring(0,200)+"..."))}catch(a){}r+="<div class='url-item "+t+"' data-url='"+u.toLowerCase()+"' data-title='"+v.toLowerCase()+"'>\n",r+="<span class='url-type type-"+t+"'>"+p.type+"</span>\n",r+="<div class='url-title'>"+v.replace(/</g,"&lt;").replace(/>/g,"&gt;")+"</div>\n",r+="<a href='"+u+"' class='url-link' target='_blank'>"+u+"</a>\n",x?(r+="<div style='background: #f1f2f6; padding: 8px; margin-top: 5px; border-radius: 3px;'>\n",r+="<strong>Image Preview:</strong><br>\n",r+="<img src='"+u+"' style='max-width: 200px; max-height: 150px; border: 1px solid #ddd; border-radius: 3px; margin-top: 5px;' onerror='this.style.display=\"none\"; this.nextElementSibling.style.display=\"block\";'>\n",r+="<div style='display: none; color: #e74c3c; font-style: italic;'>Failed to load image preview</div>\n",r+="</div>\n"):w&&(r+="<div style='background: #f1f2f6; padding: 8px; margin-top: 5px; border-radius: 3px; font-family: monospace; font-size: 11px; color: #2f3542;'>\n",r+="<strong>Decoded content:</strong><br>"+w.replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\n/g,"<br>")+"\n",r+="</div>\n"),r+="</div>\n"}r+="</div>\n",r+="<a href='#' class='back-to-top' onclick='window.scrollTo(0,0); return false;'>↑ Top</a>\n",r+="</div>\n",r+="<script>\n",r+="function filterUrls(searchTerm) {\n",r+=" var items = document.querySelectorAll('.url-item');\n",r+=" var term = searchTerm.toLowerCase();\n",r+=" items.forEach(function(item) {\n",r+=" var url = item.getAttribute('data-url');\n",r+=" var title = item.getAttribute('data-title');\n",r+=" if(url.includes(term) || title.includes(term)) {\n",r+=" item.style.display = 'block';\n",r+=" } else {\n",r+=" item.style.display = 'none';\n",r+=" }\n",r+=" });\n",r+="}\n",r+="</script>\n</body>\n</html>";var A=new Blob([o],{type:"text/plain"}),B=URL.createObjectURL(A),C=document.createElement("a");C.href=B,C.download=a+"_urls_"+d+".txt",document.body.appendChild(C),C.click(),document.body.removeChild(C),URL.revokeObjectURL(B);var D=new Blob([r],{type:"text/html"}),E=URL.createObjectURL(D),F=document.createElement("a");F.href=E,F.download=a+"_urls_"+d+".html",document.body.appendChild(F),F.click(),document.body.removeChild(F),URL.revokeObjectURL(E),alert("URLs extracted successfully!\nFiles created:\n• "+a+"_urls_"+d+".txt\n• "+a+"_urls_"+d+".html\nTotal URLs: "+h.length)})();">
URLs Extractor
</a>
<button class="copy-btn" onclick="copyBookmarkletCode(this)">Copy Code</button>
</div>
</div>
<div class="bookmarklet-description">
Advanced URL extraction tool that creates both TXT and HTML reports with detailed analysis.
</div>
<ul class="features">
<li>Extracts links and resources with metadata</li>
<li>Creates searchable HTML report with previews</li>
<li>Handles data URLs and base64 content</li>
<li>Generates both TXT and HTML output files</li>
<li>Includes statistics and categorization</li>
</ul>
</div>
<div class="bookmarklet">
<div class="bookmarklet-header">
<div class="bookmarklet-title">🖼️ Enhanced Image Downloader</div>
<div class="button-group">
<a href="javascript:void(0)"
class="bookmarklet-link"
draggable="true"
data-bookmarklet-name="Enhanced Image Downloader"
title="Drag this button to your bookmarks bar"
data-bookmarklet-code="javascript:(function(){const a=a=>new Promise(b=>{const c=document.createElement("script");c.src=a,c.onload=b,document.head.appendChild(c)});(async function(){const b=prompt("Enter minimum image size (width or height in pixels):","300");let d;if(null===b)return;""===b||"0"===b?d=0:(d=parseInt(b),(isNaN(d)||0>d)&&(alert("Invalid input. Using default size of 300px."),d=300));const e=document.createElement("div");e.style.cssText="position: fixed; top: 20px; right: 20px; background: #333; color: white;padding: 15px; border-radius: 8px; z-index: 10001; font-family: Arial;box-shadow: 0 4px 12px rgba(0,0,0,0.3);",e.innerHTML="Scanning page for images ≥"+d+"px...<br><small>Auto-scrolling to detect lazy-loaded images</small>",document.body.appendChild(e);const f=window.scrollY,g=Math.max(.8*window.innerHeight,600),h=Math.max(document.body.scrollHeight,document.documentElement.scrollHeight);for(let a=0;a<h;a+=g)window.scrollTo(0,a),e.innerHTML="Scanning page for images...<br><small>Scrolling: "+Math.round(100*(a/h))+"%</small>",await new Promise(a=>setTimeout(a,250));window.scrollTo(0,f),e.innerHTML="Processing images...",await a("https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js");const k=new JSZip,c=[...Array.from(document.images),...Array.from(document.querySelectorAll("[style*=\"background-image\"]")),...Array.from(document.querySelectorAll("*")).filter(a=>{const b=window.getComputedStyle(a);return b.backgroundImage&&"none"!==b.backgroundImage})],l=[];Array.from(document.images).forEach(a=>{a&&a.src&&(a.naturalWidth>=d||a.naturalHeight>=d)&&l.push(a)});const i=[];if(Array.from(document.querySelectorAll("*")).forEach(a=>{const b=window.getComputedStyle(a);if(b.backgroundImage&&"none"!==b.backgroundImage){const a=b.backgroundImage.match(/url\(['"]?([^'"]+)['"]?\)/);if(a&&a[1]){const b=new Promise(b=>{const c=new Image;c.onload=function(){(this.naturalWidth>=d||this.naturalHeight>=d)&&(this.isBackgroundImage=!0,l.push(this)),b()},c.onerror=function(){b()},c.src=a[1]});i.push(b)}}}),await Promise.all(i),await new Promise(a=>setTimeout(a,1e3)),!l.length)return void alert("No images larger than "+d+"x"+d+" found.");const m=document.createElement("div");m.style.cssText="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);background: white; border: 2px solid #333; padding: 20px; z-index: 10000;max-width: 80vw; max-height: 80vh; overflow: auto; border-radius: 8px;box-shadow: 0 4px 20px rgba(0,0,0,0.3);";const n=l.filter(a=>a&&a.src).map((a,b)=>"<label style=\"display: block; margin: 5px 0; padding: 5px; border: 1px solid #ddd;\"><input type=\"checkbox\" checked data-index=\""+b+"\" class=\"image-checkbox\"><img src=\""+(a.src||a.getAttribute("data-src")||"")+"\" style=\"max-width: 100px; max-height: 100px; margin: 0 10px; vertical-align: middle;\"><span>"+(a.naturalWidth||"?")+"x"+(a.naturalHeight||"?")+"px</span></label>").join("");m.innerHTML="<h3>Found "+l.length+" images (≥"+d+"px)</h3><div style=\"margin: 10px 0; padding: 10px; background: #f5f5f5; border-radius: 4px;\"><h4>Options:</h4><label style=\"display: block; margin: 5px 0;\"><input type=\"checkbox\" id=\"useOriginalNames\" checked>Keep original image filenames</label><label style=\"display: block; margin: 5px 0;\"><input type=\"checkbox\" id=\"includeReadme\" checked>Include README file with page info</label><label style=\"display: block; margin: 5px 0;\"><input type=\"checkbox\" id=\"usePageNameInZip\" checked>Use page name in ZIP filename</label><label style=\"display: block; margin: 5px 0;\"><input type=\"checkbox\" id=\"selectAll\" checked>Select/Deselect All</label></div><p>Select images to download:</p><div style=\"max-height: 400px; overflow-y: auto; margin: 10px 0;\">"+n+"</div><button id=\"downloadSelected\">Download Selected</button><button id=\"cancelDownload\">Cancel</button>",document.body.appendChild(m),document.getElementById("selectAll").onchange=function(){const a=m.querySelectorAll(".image-checkbox");a.forEach(a=>a.checked=this.checked)},document.getElementById("downloadSelected").onclick=async function(){const b=Array.from(m.querySelectorAll("input[type=\"checkbox\"]:checked")).map(a=>parseInt(a.dataset.index)).filter(a=>l[a]&&l[a].src),e=document.getElementById("useOriginalNames").checked,f=document.getElementById("includeReadme").checked,g=document.getElementById("usePageNameInZip").checked;if(!b.length)return void alert("No valid images selected!");document.body.removeChild(m);const h=(a,b)=>{try{const b=new URL(a,window.location.href),c=b.pathname,d=c.split("/").pop();if(d&&d.includes("."))return d.split("?")[0]}catch(a){console.log("Error parsing URL:",a)}return b},i=a=>a.replace(/[<>:"/\\|?*]/g,"_").replace(/\s+/g,"_"),n=[],j=new Set,o=b.map(a=>{const b=l[a];if(!b||!b.src)return console.warn("Skipping invalid image at index "+a),Promise.resolve();const c=b.src||b.getAttribute("data-src");if(!c)return console.warn("No URL found for image at index "+a),Promise.resolve();let d;if(e){const b=h(c,"image_"+(a+1)),e=b.includes(".")?"":c.split(".").pop().split("?")[0]||"jpg",f=b.includes(".")?b:b+"."+e;let g=f,k=1;for(;j.has(g);){const a=f.replace(/\.[^/.]+$/,""),b=f.includes(".")?f.split(".").pop():"";g=b?a+"_"+k+"."+b:a+"_"+k,k++}d=i(g),j.add(d)}else{const e=c.split(".").pop().split("?")[0]||"jpg";d="image_"+(a+1)+"_"+(b.naturalWidth||0)+"x"+(b.naturalHeight||0)+"."+e}return n.push({originalFilename:d,url:c,width:b.naturalWidth||0,height:b.naturalHeight||0,isBackgroundImage:b.isBackgroundImage||!1,originalUrl:c}),fetch(c).then(a=>a.blob()).then(a=>k.file(d,a)).catch(a=>(console.error("Failed to fetch "+c+":",a),null))}).filter(a=>a);if(await Promise.all(o),k.file("images_metadata.json",JSON.stringify(n,null,2)),f){const a=document.title||"Unknown Page",c=window.location.href,h=new Date().toISOString(),i=n.map((a,b)=>b+1+". "+a.originalFilename+" ("+a.width+"x"+a.height+"px)").join("\n"),j="# Images Downloaded from: "+a+"\n\n**Source URL:** "+c+"\n**Download Date:** "+h+"\n**Total Images:** "+b.length+"\n**Minimum Size Filter:** "+d+"px\n\n## Download Options Used:\n- Original filenames: "+(e?"Yes":"No")+"\n- README included: "+(f?"Yes":"No")+"\n- Page name in ZIP: "+(g?"Yes":"No")+"\n\n## Images List:\n"+i+"\n\n---\nGenerated by Enhanced Image Downloader Bookmarklet\n";k.file("README.md",j)}const p=await k.generateAsync({type:"blob"}),c=document.createElement("a");c.href=URL.createObjectURL(p);let a;if(g){const b=document.title||"webpage",c=i(b).substring(0,50),d=new Date().toISOString().slice(0,10);a=c+"_"+d+"_images.zip"}else a="images_"+d+"px_"+new Date().toISOString().slice(0,10)+".zip";c.download=a,c.click(),alert("Downloaded "+b.length+" images as \""+a+"\"!")},document.getElementById("cancelDownload").onclick=function(){document.body.removeChild(m)},e.parentNode&&document.body.removeChild(e)})()})();">
Image Downloader
</a>
<button class="copy-btn" onclick="copyBookmarkletCode(this)">Copy Code</button>
</div>
</div>
<div class="bookmarklet-description">
Advanced image downloader with size filtering, auto-scrolling, and comprehensive metadata.
</div>
<ul class="features">
<li>Interactive size filtering with custom thresholds</li>
<li>Auto-scrolls to detect lazy-loaded images</li>
<li>Selective download with preview interface</li>
<li>Original filename preservation options</li>
<li>Includes README and metadata generation</li>
</ul>
</div>
<div class="bookmarklet">
<div class="bookmarklet-header">
<div class="bookmarklet-title">📄 LinkedIn OSINT Extractor</div>
<div class="button-group">
<a href="javascript:void(0)"
class="bookmarklet-link"
draggable="true"
data-bookmarklet-name="LinkedIn OSINT Extractor"
title="Drag this button to your bookmarks bar"
data-bookmarklet-code="javascript:(function(){'use strict';try{function a(a){if(!a)return null;try{const b=a.match(/activity:[0-9]+,([0-9]+)/);if(!b||!b[1])return console.log("[OSINT] No timestamp found in activity URN:",a),null;const c=b[1],d=BigInt(c).toString(2),e=d.slice(0,41),f=parseInt(e,2),g=new Date(f),h=g.getFullYear();return 2020>h||2030<h?(console.log("[OSINT] Invalid timestamp extracted:",f,"Date:",g),null):f}catch(a){return console.error("[OSINT] Timestamp extraction error:",a),null}}function b(a){if(!a)return"Unknown date";const b=new Date(a);return{utc:b.toUTCString(),iso:b.toISOString(),unix:a,local:b.toString()}}function c(a){try{const b=a.querySelector(".comments-comment-meta__actor a"),c=a.querySelector(".comments-comment-meta__description-title"),d={name:c?.textContent.trim()||"Unknown Author",profileUrl:b?.href||"",publicId:b?.href.match(/\/in\/([^\/\?]+)/)?.[1]||"",headline:a.querySelector(".comments-comment-meta__description-subtitle")?.textContent.trim()||"",badge:a.querySelector(".comments-comment-meta__badge")?.textContent.trim()||"",isPremium:!!a.querySelector(".premium-icon"),isInfluencer:!!a.querySelector("li-icon[type=\"linkedin-bug-influencer-color\"]"),connectionDegree:a.querySelector(".comments-comment-meta__data")?.textContent.trim().replace("\u2022","").trim()||""};return d}catch(a){return console.error("[OSINT] Author data extraction error:",a),{name:"Error extracting author",error:a.message}}}function d(a){try{const b=a.querySelector(".comments-comment-item__main-content");if(!b)return{text:"No content found",mentions:[],hashtags:[]};const c=b.textContent.trim(),d=Array.from(b.querySelectorAll("a[data-attribute-index]")).map(a=>({name:a.textContent.trim(),url:a.href,publicId:a.href.match(/\/in\/([^\/\?]+)/)?.[1]||""})),e=Array.from(b.querySelectorAll("a[href*=\"hashtag\"]")).map(a=>a.textContent.trim().replace("#","")),f=!!a.querySelector(".comments-comment-item__edited-badge");return{text:c,mentions:d,hashtags:e,isEdited:f}}catch(a){return console.error("[OSINT] Content extraction error:",a),{text:"Error extracting content",error:a.message,mentions:[],hashtags:[]}}}function e(a){try{const b=a.querySelector(".comments-comment-social-bar__reactions-count--cr");let c="0";if(b){const a=b.getAttribute("aria-label"),d=a?.match(/(\d+)\s+[Rr]eaction/);c=d?d[1]:b.textContent.trim()||"0"}const d=Array.from(a.querySelectorAll(".reactions-icon")).map(a=>a.alt||a.title||"").filter(a=>a&&"like"!==a),e=a.querySelector(".comments-comment-social-bar__replies-count--cr");let f=0;if(e){const a=e.textContent.trim(),b=a.match(/(\d+)\s+repl/i);f=b?parseInt(b[1]):0}return{reactions:{count:c,types:0<d.length?d:["like"]},replies:f}}catch(a){return console.error("[OSINT] Engagement data extraction error:",a),{reactions:{count:"0",types:[]},replies:0}}}function f(a){try{const b={images:[],videos:[],sharedArticle:null,sharedPost:null},c=a.querySelectorAll(".comments-comment-item__media img");b.images=Array.from(c).map(a=>({url:a.src||a.dataset.src||"",alt:a.alt||""}));const d=a.querySelectorAll(".comments-comment-item__media video");b.videos=Array.from(d).map(a=>({url:a.src||a.dataset.src||"",poster:a.poster||""}));const e=a.querySelector(".comments-comment-shared-article");return e&&(b.sharedArticle={url:e.querySelector("a")?.href||"",title:e.querySelector(".comments-comment-shared-article__title")?.textContent.trim()||"",description:e.querySelector(".comments-comment-shared-article__description")?.textContent.trim()||""}),b}catch(a){return console.error("[OSINT] Media extraction error:",a),{images:[],videos:[],sharedArticle:null,sharedPost:null}}}function g(a){return a?(a=(a+"").replace(/"/g,'""'),a.includes(",")||a.includes("\n")||a.includes('"')?%60"${a}"%60:a):""}function h(a,b,c){const d=new Blob([a],{type:b}),e=document.createElement("a");e.href=URL.createObjectURL(d),e.download=c,e.click()}console.log("[OSINT Extractor] Starting extraction...");const i=window.location.href,j=new Date,k=j.toISOString().replace(/[:.]/g,"-").slice(0,19),l=j.toISOString().split("T")[0],m=function(a){var b=0;if(0==a.length)return b;for(var c,d=0;d<a.length;d++)c=a.charCodeAt(d),b=(b<<5)-b+c,b&=b;return Math.abs(b).toString(16)}(i+l),n=document.querySelectorAll(".comments-comment-entity");if(!n.length)return void alert("No comments found! Please scroll to load all comments first.");const o=function(){const a=window.location.href,b=/\/posts\/[^\/]+_[^\/]+-activity-\d+-/.test(a),c=!!document.querySelector(".feed-shared-article, .feed-shared-update-v2__description-wrapper .feed-shared-article"),d=!!document.querySelector(".feed-shared-external-video, .feed-shared-linkedin-video");return b&&(c||d||document.querySelector(".update-components-text"))}();console.log(%60[OSINT] Found ${n.length} comments to extract%60),console.log(%60[OSINT] Post type detected: ${o?"Link Post":"Regular/Comment-only extraction"}%60);const p=function(){if(!o)return{warning:"Not a link post - only extracting comments",author:{name:"N/A"},content:"N/A",timestamp:"N/A",engagement:{reactions:"N/A",comments:"N/A",reposts:"N/A"}};console.log("[OSINT] Extracting post data...");try{const a=document.querySelector(".update-components-actor__title .t-bold span[dir=\"ltr\"]"),b=a?.textContent.trim()||document.querySelector(".update-components-actor__title")?.textContent.trim()||"Unknown",c=document.querySelector(".social-details-social-counts__reactions-count"),d=c?.textContent.trim()||document.querySelector(".social-details-social-counts__reactions button")?.textContent.trim().match(/\d+/)?.[0]||"0",e=document.querySelector(".social-details-social-counts__comments button")?.textContent.trim()||"",f=e.match(/\d+/)?.[0]||"0",g=Array.from(document.querySelectorAll(".social-details-social-counts__item button")).find(a=>a.textContent.includes("repost"))?.textContent.trim()||"",h=g.match(/\d+/)?.[0]||"0",i={author:{name:b,headline:document.querySelector(".update-components-actor__description")?.textContent.trim()||"",link:document.querySelector(".update-components-actor__meta-link")?.href||document.querySelector(".update-components-actor__container a")?.href||""},content:document.querySelector(".feed-shared-update-v2__description")?.textContent.trim()||"",timestamp:document.querySelector(".update-components-actor__sub-description")?.textContent.trim().split("\u2022")[0]?.trim()||"",engagement:{reactions:d,comments:f,reposts:h}};return i}catch(a){return console.error("[OSINT] Post data extraction error:",a),{error:a.message}}}(),q=[],r=new Map;Array.from(n).forEach((g,h)=>{try{const i=g.getAttribute("data-id")||"",j=a(i),k=b(j),l=g.classList.contains("comments-comment-item--reply");let m=null;if(l){const a=g.closest(".comments-comments-list__comment-item"),b=a?.querySelector(".comments-comment-entity:not(.comments-comment-item--reply)");if(b){const a=b.getAttribute("data-id");m=r.get(a)}}const o={id:i,index:h+1,author:c(g),content:d(g),metadata:{relativeDate:g.querySelector("time.comments-comment-meta__data")?.textContent.trim()||"",dates:k,timestamp:j,isReply:l,parentAuthor:m,threadDepth:g.querySelectorAll(".comments-comment-item--reply").length},engagement:e(g),media:f(g)};!l&&o.author.publicId&&r.set(i,o.author),q.push(o),console.log(%60[OSINT] Extracted comment ${h+1}/${n.length}%60)}catch(a){console.error(%60[OSINT] Error extracting comment ${h+1}:%60,a),q.push({id:"error-"+h,index:h+1,error:a.message})}});const s=new Map;q.forEach(a=>{a.author?.publicId&&!a.error&&(!s.has(a.author.publicId)&&s.set(a.author.publicId,{name:a.author.name,profileUrl:a.author.profileUrl,headline:a.author.headline,commentCount:0}),s.get(a.author.publicId).commentCount++)});const t={metadata:{extractionDate:j.toISOString(),extractorVersion:"2.1.0",url:i,title:document.title,totalComments:q.length,uniqueCommenters:s.size,isLinkPost:o},post:p,comments:q,topCommenters:Array.from(s.values()).sort((c,a)=>a.commentCount-c.commentCount).slice(0,10),timeline:{earliest:q.filter(a=>a.metadata?.timestamp).sort((c,a)=>c.metadata.timestamp-a.metadata.timestamp)[0],latest:q.filter(a=>a.metadata?.timestamp).sort((c,a)=>a.metadata.timestamp-c.metadata.timestamp)[0]}};console.log("[OSINT] Generating outputs...");const u={txt:function(a){let b=%60LinkedIn OSINT Comment Extraction Report\n%60;b+=%60=====================================\n%60,b+=%60URL: ${a.metadata.url}\n%60,b+=%60Title: ${a.metadata.title}\n%60,b+=%60Extraction Date: ${a.metadata.extractionDate}\n%60,b+=%60Total Comments: ${a.metadata.totalComments}\n%60,b+=%60Unique Commenters: ${a.metadata.uniqueCommenters}\n%60,b+=%60Post Type: ${a.metadata.isLinkPost?"Link Post":"Comment-only extraction"}\n\n%60,a.metadata.isLinkPost||(b+="\u26A0\uFE0F WARNING: You are not on a link Post I will only extract comments\n\n"),a.metadata.isLinkPost&&(b+=%60POST INFORMATION\n%60,b+=%60================\n%60,b+=%60Author: ${a.post.author?.name||"Unknown"}\n%60,b+=%60Headline: ${a.post.author?.headline||"N/A"}\n%60,b+=%60Profile: ${a.post.author?.link||"N/A"}\n%60,b+=%60Posted: ${a.post.timestamp||"Unknown"}\n%60,b+=%60Reactions: ${a.post.engagement?.reactions||"0"}\n%60,b+=%60Comments: ${a.post.engagement?.comments||"0"}\n%60,b+=%60Reposts: ${a.post.engagement?.reposts||"0"}\n\n%60,b+=%60Content:\n${a.post.content||"No content found"}\n\n%60,b+=%60TOP COMMENTERS\n%60,b+=%60==============\n%60,a.topCommenters.forEach((a,c)=>{b+=%60${c+1}. ${a.name} - ${a.commentCount} comments\n%60})),b+=%60\n\nCOMMENTS (Chronological Order)\n%60,b+=%60===============================\n\n%60;const c=a.comments.filter(a=>a.metadata?.timestamp).sort((c,a)=>c.metadata.timestamp-a.metadata.timestamp);return c.forEach(a=>{b+=%60#${a.index}\n%60,b+=%60Author: ${a.author?.name||"Unknown"}\n%60,b+=%60Profile: ${a.author?.profileUrl||"N/A"}\n%60,b+=%60Headline: ${a.author?.headline||"N/A"}\n%60,b+=%60Badge: ${a.author?.badge||"None"}\n%60,b+=%60Connection: ${a.author?.connectionDegree||"N/A"}\n%60,b+=%60Posted: ${a.metadata?.dates?.utc||"Unknown"}\n%60,b+=%60Relative: ${a.metadata?.relativeDate||"Unknown"}\n%60,b+=%60Comment ID: ${a.id}\n%60,b+=%60Is Reply: ${a.metadata?.isReply?"Yes":"No"}\n%60,a.metadata?.parentAuthor&&(b+=%60Replying to: ${a.metadata.parentAuthor.name}\n%60),b+=%60Reactions: ${a.engagement?.reactions?.count||"0"} (${a.engagement?.reactions?.types?.join(", ")||"None"})\n%60,b+=%60Replies: ${a.engagement?.replies||"0"}\n%60,0<a.content?.mentions?.length&&(b+=%60Mentions: ${a.content.mentions.map(a=>%60@${a.name}%60).join(", ")}\n%60),0<a.content?.hashtags?.length&&(b+=%60Hashtags: ${a.content.hashtags.map(a=>%60#${a}%60).join(", ")}\n%60),0<a.media?.images?.length&&(b+=%60Images: ${a.media.images.length} attached\n%60),a.content?.isEdited&&(b+=%60[EDITED]\n%60),b+=%60\nContent:\n${a.content?.text||"No content"}\n\n%60,b+=%60----------------------------------------\n\n%60}),b}(t),json:JSON.stringify(t,null,2),html:function(a){const b=a.metadata.isLinkPost,c=b?"":%60 <div class="card" style="background: #fff3cd; border-left: 4px solid #ffc107;"> <h2 style="color: #856404;">⚠%EF%B8%8F Notice</h2> <p style="color: #856404; margin: 0;">You are not on a link Post I will only extract comments</p> </div>%60,d=b?%60 <div class="card"> <h2>Post Information</h2> <div class="post-info"> <a href="${a.post.author?.link||"#"}" target="_blank" class="post-author">${a.post.author?.name||"Unknown Author"}</a> <div class="post-headline">${a.post.author?.headline||""}</div> <div class="comment-metadata">Posted: ${a.post.timestamp||"Unknown"}</div> </div> <div class="engagement-stats"> <div class="engagement-stat">👍 ${a.post.engagement?.reactions||"0"} reactions</div> <div class="engagement-stat">💬 ${a.post.engagement?.comments||"0"} comments</div> <div class="engagement-stat">🔄 ${a.post.engagement?.reposts||"0"} reposts</div> </div> ${a.post.content?%60<div class="post-content">${a.post.content}</div>%60:""} </div>%60:"",e=b?%60 <div class="card"> <h2>Top Commenters</h2> <div class="top-commenters"> <ol> ${a.topCommenters.map(a=>%60<li><strong>${a.name}</strong> - ${a.commentCount} comment${1<a.commentCount?"s":""}</li>%60).join("")} </ol> </div> </div>%60:"",f=b?%60 <div class="card"> <h2>Comments Analysis</h2> <div class="metrics"> <div class="metric"> <span class="metric-value">${a.comments.length}</span> <span class="metric-label">Total Comments</span> </div> <div class="metric"> <span class="metric-value">${a.metadata.uniqueCommenters}</span> <span class="metric-label">Unique Commenters</span> </div> <div class="metric"> <span class="metric-value">${a.comments.filter(a=>a.metadata?.isReply).length}</span> <span class="metric-label">Replies</span> </div> <div class="metric"> <span class="metric-value">${a.comments.filter(a=>0<a.content?.mentions?.length).length}</span> <span class="metric-label">Comments with Mentions</span> </div> </div> </div>%60:"",g=%60<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>LinkedIn OSINT Report - ${new Date(a.metadata.extractionDate).toLocaleDateString()}</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; line-height: 1.6; color: #333; background: #f8f9fa; } .container { max-width: 1200px; margin: 0 auto; padding: 20px; } .header { background: linear-gradient(135deg, #0077b5 0%, #004471 100%); color: white; padding: 40px; border-radius: 12px; margin-bottom: 30px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } .header h1 { font-size: 2.5em; margin-bottom: 10px; font-weight: 300; } .header .subtitle { font-size: 1.1em; opacity: 0.9; } .card { background: white; border-radius: 12px; padding: 30px; margin-bottom: 20px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); } .card h2 { color: #0077b5; margin-bottom: 20px; font-size: 1.8em; font-weight: 400; } .post-info { border-left: 4px solid #0077b5; padding-left: 20px; margin-bottom: 20px; } .post-author { font-size: 1.2em; font-weight: 600; color: #0077b5; text-decoration: none; display: inline-block; margin-bottom: 5px; } .post-author:hover { text-decoration: underline; } .post-headline { color: #666; margin-bottom: 10px; } .post-content { background: #f8f9fa; padding: 20px; border-radius: 8px; margin: 20px 0; white-space: pre-wrap; } .metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin: 20px 0; } .metric { background: #f8f9fa; padding: 20px; border-radius: 8px; text-align: center; } .metric-value { font-size: 2em; font-weight: bold; color: #0077b5; display: block; } .metric-label { color: #666; font-size: 0.9em; margin-top: 5px; } .comment { background: #fff; border: 1px solid #e0e0e0; border-radius: 8px; padding: 20px; margin-bottom: 15px; transition: box-shadow 0.2s; } .comment:hover { box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05); } .comment.reply { margin-left: 40px; border-left: 3px solid #0077b5; } .comment-header { display: flex; justify-content: space-between; align-items: start; margin-bottom: 15px; } .comment-author-info { flex: 1; } .comment-author { font-weight: 600; color: #0077b5; text-decoration: none; font-size: 1.1em; } .comment-author:hover { text-decoration: underline; } .comment-headline { color: #666; font-size: 0.9em; margin-top: 3px; } .comment-metadata { color: #999; font-size: 0.85em; margin-top: 5px; } .comment-content { margin: 15px 0; line-height: 1.6; } .comment-actions { display: flex; gap: 20px; margin-top: 15px; font-size: 0.9em; color: #666; } .badge { display: inline-block; background: #e7f3ff; color: #0077b5; padding: 2px 8px; border-radius: 4px; font-size: 0.8em; margin-left: 10px; } .edited { color: #ff6b6b; font-size: 0.85em; font-style: italic; } .mention { color: #0077b5; font-weight: 500; } .hashtag { color: #0077b5; } .top-commenters { background: #f8f9fa; padding: 20px; border-radius: 8px; } .top-commenters ol { padding-left: 20px; } .top-commenters li { margin-bottom: 10px; color: #333; } .metadata-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; background: #f8f9fa; padding: 20px; border-radius: 8px; } .metadata-item { display: flex; flex-direction: column; } .metadata-label { font-weight: 600; color: #666; font-size: 0.85em; text-transform: uppercase; letter-spacing: 0.5px; } .metadata-value { color: #333; margin-top: 5px; } .engagement-stats { display: flex; gap: 15px; font-size: 0.9em; } .engagement-stat { display: flex; align-items: center; gap: 5px; } @media (max-width: 768px) { .container { padding: 10px; } .header { padding: 30px 20px; } .header h1 { font-size: 2em; } .card { padding: 20px; } .comment.reply { margin-left: 20px; } .metrics { grid-template-columns: 1fr; } } </style></head><body> <div class="container"> <div class="header"> <h1>LinkedIn OSINT Analysis Report</h1> <div class="subtitle">${a.metadata.title}</div> </div> ${c} <div class="card"> <h2>Extraction Metadata</h2> <div class="metadata-grid"> <div class="metadata-item"> <span class="metadata-label">URL</span> <span class="metadata-value"><a href="${a.metadata.url}" target="_blank">${a.metadata.url}</a></span> </div> <div class="metadata-item"> <span class="metadata-label">Extraction Date</span> <span class="metadata-value">${new Date(a.metadata.extractionDate).toLocaleString()}</span> </div> <div class="metadata-item"> <span class="metadata-label">Total Comments</span> <span class="metadata-value">${a.metadata.totalComments}</span> </div> <div class="metadata-item"> <span class="metadata-label">Unique Commenters</span> <span class="metadata-value">${a.metadata.uniqueCommenters}</span> </div> <div class="metadata-item"> <span class="metadata-label">Post Type</span> <span class="metadata-value">${a.metadata.isLinkPost?"Link Post":"Comment-only extraction"}</span> </div> </div> </div> ${d} ${e} ${f} <div class="card"> <h2>All Comments</h2> ${a.comments.map(a=>a.error?%60<div class="comment"><div class="edited">Error extracting comment ${a.index}: ${a.error}</div></div>%60:%60 <div class="comment ${a.metadata?.isReply?"reply":""}"> <div class="comment-header"> <div class="comment-author-info"> <div> <a href="${a.author?.profileUrl||"#"}" target="_blank" class="comment-author">${a.author?.name||"Unknown"}</a> ${a.author?.badge?%60<span class="badge">${a.author.badge}</span>%60:""} </div> ${a.author?.headline?%60<div class="comment-headline">${a.author.headline}</div>%60:""} <div class="comment-metadata"> ${a.metadata?.dates?.utc||"Unknown date"} ${a.metadata?.relativeDate?%60(${a.metadata.relativeDate})%60:""} ${a.author?.connectionDegree?%60 • ${a.author.connectionDegree}%60:""} </div> </div> </div> ${a.metadata?.isReply&&a.metadata?.parentAuthor?%60<div style="color: #666; font-size: 0.9em; margin-bottom: 10px;">↳ Replying to ${a.metadata.parentAuthor.name}</div>%60:""} <div class="comment-content"> ${a.content?.isEdited?"<span class=\"edited\">[EDITED]</span> ":""} ${a.content?.text||"No content"} </div> ${0<a.content?.mentions?.length?%60<div style="margin-top: 10px;">Mentions: ${a.content.mentions.map(a=>%60<span class="mention">@${a.name}</span>%60).join(", ")}</div>%60:""} ${0<a.content?.hashtags?.length?%60<div style="margin-top: 5px;">Hashtags: ${a.content.hashtags.map(a=>%60<span class="hashtag">#${a}</span>%60).join(", ")}</div>%60:""} <div class="comment-actions"> <span>👍 ${a.engagement?.reactions?.count||"0"} reactions</span> <span>💬 ${a.engagement?.replies||"0"} replies</span> ${0<a.media?.images?.length?%60<span>📷 ${a.media.images.length} image(s)</span>%60:""} </div> </div>%60).join("")} </div> </div></body></html>%60;return g}(t),csv:function(a){let b="Comment_Index,Author_Name,Author_PublicID,Author_ProfileURL,Author_Headline,Author_Badge,Connection_Degree,Is_Reply,Parent_Author,Timestamp_UTC,Timestamp_Unix,Relative_Date,Reactions_Count,Reaction_Types,Replies_Count,Mentions,Hashtags,Has_Images,Is_Edited,Content\n";return a.comments.forEach(a=>{if(!a.error){const c=[a.index,g(a.author?.name||"Unknown"),g(a.author?.publicId||""),g(a.author?.profileUrl||""),g(a.author?.headline||""),g(a.author?.badge||""),g(a.author?.connectionDegree||""),a.metadata?.isReply?"Yes":"No",g(a.metadata?.parentAuthor?.name||""),g(a.metadata?.dates?.utc||""),a.metadata?.timestamp||"",g(a.metadata?.relativeDate||""),a.engagement?.reactions?.count||"0",g(a.engagement?.reactions?.types?.join(";")||""),a.engagement?.replies||"0",g(a.content?.mentions?.map(a=>a.name).join(";")||""),g(a.content?.hashtags?.join(";")||""),0<a.media?.images?.length?"Yes":"No",a.content?.isEdited?"Yes":"No",g(a.content?.text||"")];b+=c.join(",")+"\n"}}),b}(t)},v=%60LinkedIn-OSINT-Extract_${k}_${m}%60;h(u.txt,"text/plain",%60${v}.txt%60),setTimeout(()=>h(u.json,"application/json",%60${v}.json%60),100),setTimeout(()=>h(u.html,"text/html",%60${v}.html%60),200),setTimeout(()=>h(u.csv,"text/csv",%60${v}.csv%60),300);const w=%60LinkedIn OSINT Extraction Complete!\n${o?"":"\u26A0\uFE0F WARNING: You are not on a link Post I will only extract comments\n\n"}Extracted: ${q.length} comments\nUnique users: ${s.size}\nPost Type: ${o?"Link Post":"Comment-only extraction"}\nFiles saved: TXT, JSON, HTML, CSV\n\nCheck your downloads folder for:\n- ${v}.txt\n- ${v}.json \n- ${v}.html\n- ${v}.csv%60;alert(w),console.log("[OSINT] Extraction complete!",t)}catch(a){console.error("[OSINT] Fatal error:",a),alert("OSINT Extraction Error: "+a.message)}})();">
LinkedIn OSINT
</a>
<button class="copy-btn" onclick="copyBookmarkletCode(this)">Copy Code</button>
</div>
</div>
<div class="bookmarklet-description">
Advanced LinkedIn OSINT tool that extracts comprehensive post and comment data with detailed analysis.
</div>
<ul class="features">
<li>Extracts post information and author details</li>
<li>Captures comments with precise timestamps</li>
<li>Generates TXT, JSON, HTML, and CSV reports</li>
<li>Includes engagement metrics and user analysis</li>
<li>Provides chronological timeline and top commenters</li>
</ul>
</div>
<div class="bookmarklet">
<div class="bookmarklet-header">
<div class="bookmarklet-title">🔍 Domain OSINT Hub</div>
<div class="button-group">
<a href="javascript:void(0)"
class="bookmarklet-link"
draggable="true"
data-bookmarklet-name="Domain OSINT Hub"
title="Drag this button to your bookmarks bar"
data-bookmarklet-code="javascript:!function(){"use strict";const e="2.0.1",n="domainOSINTHubV2",t=150,o=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)||window.innerWidth<=768;if(window.domainOSINTHub)try{return void window.domainOSINTHub.focus()}catch(r){}try{const i={reputation:{name:"Reputation & Threat Intelligence",icon:"🛡️",color:"#ef4444",services:[{name:"VirusTotal",url:"https://www.virustotal.com/gui/domain/{domain}"},{name:"URLVoid",url:"https://www.urlvoid.com/scan/{domain}"},{name:"AlienVault OTX",url:"https://otx.alienvault.com/indicator/domain/{domain}"},{name:"ThreatCrowd",url:"https://www.threatcrowd.org/searchApi/v2/domain/report/?domain={domain}"},{name:"Google Safe Browsing",url:"https://transparencyreport.google.com/safe-browsing/search?url={domain}"},{name:"Talos Intelligence",url:"https://talosintelligence.com/reputation_center/lookup?search={domain}"},{name:"IPVoid",url:"https://www.ipvoid.com/scan/{domain}/"}]},certificates:{name:"Certificates & SSL",icon:"🔐",color:"#10b981",services:[{name:"crt.sh Certificates",url:"https://crt.sh/?q={domain}"},{name:"CertSpotter API",url:"https://api.certspotter.com/v1/issuances?domain={domain}&include_subdomains=true&expand=dns_names"},{name:"SSL Labs",url:"https://www.ssllabs.com/ssltest/analyze.html?hideResults=on&d={domain}",longProcess:!0}]},dns:{name:"DNS & Network Infrastructure",icon:"🌐",color:"#3b82f6",services:[{name:"Robtex",url:"https://www.robtex.com/dns-lookup/{domain}"},{name:"SecurityTrails",url:"https://securitytrails.com/domain/{domain}/dns"},{name:"DNSlytics",url:"https://dnslytics.com/domain/{domain}"},{name:"DNSDumpster",url:"https://dnsdumpster.com/"},{name:"MXToolbox",url:"https://mxtoolbox.com/SuperTool.aspx?action=a&run=toolpage&txtinput={domain}"},{name:"ViewDNS IP History",url:"https://viewdns.info/iphistory/?domain={domain}"},{name:"ViewDNS Reverse IP",url:"https://viewdns.info/reverseip/?host={domain}&t=1"}]},whois:{name:"WHOIS & Registration",icon:"📋",color:"#8b5cf6",services:[{name:"DomainTools WHOIS",url:"https://whois.domaintools.com/{domain}"},{name:"ViewDNS WHOIS",url:"https://viewdns.info/whois/?domain={domain}"},{name:"Whoisology",url:"https://whoisology.com/{domain}"},{name:"WhoIsRequest",url:"https://whoisrequest.com/whois/{domain}"}]},intelligence:{name:"Intelligence & Analytics",icon:"🔍",color:"#f59e0b",services:[{name:"Shodan",url:"https://www.shodan.io/search?query=hostname:{domain}"},{name:"Host.io",url:"https://host.io/{domain}"},{name:"SpyOnWeb",url:"https://spyonweb.com/{domain}"},{name:"RiskIQ Community",url:"https://community.riskiq.com/search/{domain}"},{name:"ThreatMiner",url:"https://www.threatminer.org/domain.php?q={domain}"},{name:"Hybrid Analysis",url:"https://www.hybrid-analysis.com/search?query={domain}"}]},technology:{name:"Technology & Content",icon:"⚙️",color:"#06b6d4",services:[{name:"BuiltWith",url:"https://builtwith.com/{domain}"},{name:"Wayback Machine",url:"https://web.archive.org/web/*/{domain}/*"},{name:"Netcraft Site Report",url:"https://sitereport.netcraft.com/?url={domain}"},{name:"DomainIQ",url:"https://www.domainiq.com/domain/{domain}"}]}},a={"quick-scan":{name:"⚡ Quick Scan",description:"Essential services for rapid assessment",services:["VirusTotal","URLVoid","crt.sh Certificates","ViewDNS WHOIS","Shodan"]},"full-investigation":{name:"🔍 Full Investigation",description:"Comprehensive analysis with all available services",services:"all"},"reputation-check":{name:"🛡️ Reputation Check",description:"Focus on threat intelligence and reputation",services:["VirusTotal","URLVoid","AlienVault OTX","ThreatCrowd","Google Safe Browsing","Talos Intelligence"]},infrastructure:{name:"🌐 Infrastructure Analysis",description:"DNS, certificates, and network infrastructure",services:["crt.sh Certificates","SecurityTrails","DNSlytics","DNSDumpster","Robtex","MXToolbox","SSL Labs"]},"passive-recon":{name:"👁️ Passive Reconnaissance",description:"Non-intrusive information gathering",services:["crt.sh Certificates","Wayback Machine","ViewDNS IP History","Whoisology","Host.io","BuiltWith"]},"threat-hunting":{name:"🎯 Threat Hunting",description:"Advanced threat intelligence gathering",services:["VirusTotal","AlienVault OTX","ThreatCrowd","Hybrid Analysis","ThreatMiner","Shodan","RiskIQ Community"]}};function s(e){return String(e||"").trim().replace(/^https?:\/\//i,"").replace(/^ftp:\/\//i,"").replace(/^[\w-]+:@/i,"").replace(/\/.*$/,"").replace(/:\d+$/,"").replace(/^www\./i,"")}function c(e){return!(!e||"string"!=typeof e)&&(!(e.length>253)&&(!!/\./.test(e)&&(e.endsWith(".")&&(e=e.slice(0,-1)),/^[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?(?:\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)+$/.test(e))))}let l="";try{window.location&&window.location.hostname&&(l=s(window.location.hostname))}catch(H){l=""}if(!c(l)){const A=prompt("Enter domain for OSINT reconnaissance:",l||"example.com");if(null===A)return;l=s(A||"example.com")}if(c(l)||(l="example.com"),window.domainOSINTHub)try{window.domainOSINTHub.close()}catch($){}const d=o?"width=400,height=600,scrollbars=yes,resizable=yes":"width=700,height=800,scrollbars=yes,resizable=yes,menubar=no,toolbar=no";if(window.domainOSINTHub=window.open("",n,d),!window.domainOSINTHub)return void alert('Popup blocked! Please allow popups for this site and try again.\n\nTo enable popups:\n1. Click the popup blocker icon in your address bar\n2. Select "Always allow popups from this site"\n3. Try the bookmarklet again');const p=window.domainOSINTHub.document;p.open(),p.write('<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Domain OSINT Hub v2.0</title><meta name="viewport" content="width=device-width, initial-scale=1.0"></head><body></body></html>'),p.close();const u=p.createElement("style");function m(e,n="status"){const t=p.getElementById("statusDiv"),o=p.createElement("div");return o.className="status "+n,o.textContent=e,t.appendChild(o),setTimeout(()=>{o.parentNode&&o.parentNode.removeChild(o)},5e3),o}u.textContent=`\n * { box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n margin: 0; padding: ${o?"12px":"20px"};\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n min-height: 100vh; color: #333; line-height: 1.5;\n }\n .container {\n background: #ffffff; padding: ${o?"16px":"24px"};\n border-radius: ${o?"8px":"16px"};\n box-shadow: 0 20px 40px rgba(0,0,0,0.1); max-width: 100%;\n ${o?"min-height: calc(100vh - 24px);":""}\n }\n .header {\n text-align: center; margin-bottom: 24px; padding-bottom: 16px;\n border-bottom: 2px solid #667eea;\n }\n .header h1 {\n margin: 0; color: #2d3748; font-size: ${o?"20px":"24px"};\n font-weight: 600;\n }\n .header .subtitle {\n color: #718096; font-size: ${o?"12px":"14px"};\n margin-top: 4px;\n }\n .domain-section { margin-bottom: 20px; }\n .domain-input {\n width: 100%; padding: 12px 16px; border: 2px solid #e2e8f0;\n border-radius: 8px; font-size: 16px; transition: border-color 0.2s;\n margin-bottom: 12px;\n }\n .domain-input:focus {\n outline: none; border-color: #667eea;\n box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);\n }\n .search-container {\n margin-bottom: 20px; padding: 16px; background: #f8fafc;\n border-radius: 8px; border: 1px solid #e2e8f0;\n }\n .search-input-group { position: relative; margin-bottom: 12px; }\n .search-input {\n width: 100%; padding: 10px 40px 10px 16px; border: 1px solid #d1d5db;\n border-radius: 6px; font-size: 14px; background: white;\n }\n .search-clear {\n position: absolute; right: 8px; top: 50%; transform: translateY(-50%);\n background: none; border: none; font-size: 18px; color: #9ca3af;\n cursor: pointer; padding: 4px;\n }\n .search-filters { display: flex; gap: 6px; flex-wrap: wrap; }\n .filter-btn {\n padding: ${o?"6px 8px":"6px 12px"};\n border: 1px solid #d1d5db; border-radius: 4px; background: white;\n font-size: ${o?"11px":"12px"}; cursor: pointer;\n transition: all 0.2s;\n }\n .filter-btn:hover, .filter-btn.active {\n background: #667eea; color: white; border-color: #667eea;\n }\n .presets-section {\n margin: 20px 0; padding: 16px; background: #f8fafc;\n border-radius: 8px; border: 1px solid #e2e8f0;\n }\n .presets-header {\n display: flex; justify-content: space-between; align-items: center;\n margin-bottom: 16px;\n }\n .presets-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(${o?"140px":"280px"}, 1fr));\n gap: 12px;\n }\n .preset-card {\n background: white; border: 1px solid #e2e8f0; border-radius: 6px;\n padding: 12px; display: flex;\n ${o?"flex-direction: column;":"justify-content: space-between;"}\n align-items: center;\n transition: all 0.2s; text-align: ${o?"center":"left"};\n }\n .preset-card:hover {\n box-shadow: 0 2px 4px rgba(0,0,0,0.1); border-color: #667eea;\n }\n .preset-info {\n flex: 1; ${o?"margin-bottom: 8px;":""}\n }\n .preset-name {\n font-weight: 600; color: #2d3748;\n font-size: ${o?"12px":"14px"}; margin-bottom: 4px;\n }\n .preset-description {\n font-size: ${o?"10px":"12px"}; color: #718096;\n margin-bottom: 4px; ${o?"display: none;":""}\n }\n .preset-meta { font-size: 11px; color: #a0aec0; }\n .preset-actions { display: flex; gap: 4px; }\n .button-group {\n display: flex; gap: 8px; margin-bottom: 20px;\n ${o?"flex-direction: column;":"flex-wrap: wrap;"}\n }\n .btn {\n padding: 10px 16px; border: none; border-radius: 8px;\n font-size: 14px; font-weight: 500; cursor: pointer;\n transition: all 0.2s;\n ${o?"width: 100%;":"flex: 1; min-width: 120px;"}\n }\n .btn-primary { background: #667eea; color: white; }\n .btn-primary:hover { background: #5a6fd8; transform: translateY(-1px); }\n .btn-secondary { background: #e2e8f0; color: #4a5568; }\n .btn-secondary:hover { background: #cbd5e0; }\n .btn-success { background: #48bb78; color: white; }\n .btn-success:hover { background: #38a169; transform: translateY(-1px); }\n .btn:disabled {\n opacity: 0.6; cursor: not-allowed; transform: none !important;\n }\n .btn-mini {\n padding: 4px 8px; border: none; border-radius: 4px;\n font-size: 11px; font-weight: 500; cursor: pointer;\n background: #667eea; color: white; transition: all 0.2s;\n }\n .btn-mini:hover { background: #5a6fd8; transform: translateY(-1px); }\n .services-header {\n display: flex; justify-content: space-between; align-items: center;\n margin-bottom: 16px;\n }\n .services-title {\n font-size: 18px; font-weight: 600; color: #2d3748; margin: 0;\n }\n .counter {\n background: #667eea; color: white; padding: 4px 8px;\n border-radius: 12px; font-size: 12px; font-weight: 500;\n }\n .services-list {\n max-height: ${o?"60vh":"400px"}; overflow-y: auto;\n border: 1px solid #e2e8f0; border-radius: 8px; padding: 12px;\n background: #f8fafc;\n }\n .category-header {\n display: flex; justify-content: space-between; align-items: center;\n padding: 12px 16px; margin: 8px 0 4px 0;\n background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);\n border-radius: 8px; border-left: 4px solid var(--category-color, #667eea);\n position: sticky; top: 0; z-index: 10;\n }\n .category-info { display: flex; align-items: center; gap: 8px; }\n .category-icon { font-size: 16px; }\n .category-name {\n font-weight: 600; color: #2d3748; font-size: 14px;\n }\n .category-count {\n background: #667eea; color: white; padding: 2px 6px;\n border-radius: 8px; font-size: 11px; font-weight: 500;\n }\n .category-services {\n margin-left: 16px; border-left: 2px solid #e2e8f0;\n padding-left: 16px; margin-bottom: 16px;\n }\n .service-item {\n display: flex; align-items: center; padding: 6px 0;\n border-bottom: 1px solid #e2e8f0;\n }\n .service-item:last-child { border-bottom: none; }\n .service-checkbox {\n margin-right: 12px; width: 16px; height: 16px;\n accent-color: #667eea;\n }\n .service-label {\n flex: 1; font-size: 14px; color: #4a5568; cursor: pointer;\n user-select: none;\n }\n .service-label:hover { color: #2d3748; }\n .long-process { color: #d69e2e !important; font-weight: 500; }\n .export-section {\n margin: 24px 0; padding: 20px; background: #f8fafc;\n border-radius: 8px; border: 1px solid #e2e8f0;\n }\n .section-title {\n font-size: 16px; font-weight: 600; color: #2d3748;\n margin: 0 0 12px 0;\n }\n .export-buttons {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(${o?"120px":"140px"}, 1fr));\n gap: 8px;\n }\n .btn-export {\n padding: 10px 12px; border: 1px solid #d1d5db; border-radius: 6px;\n background: white; color: #374151; font-size: 13px; font-weight: 500;\n cursor: pointer; transition: all 0.2s;\n }\n .btn-export:hover {\n background: #f3f4f6; border-color: #9ca3af; transform: translateY(-1px);\n }\n .status {\n background: #e6fffa; border: 1px solid #81e6d9; border-radius: 6px;\n padding: 8px 12px; margin: 8px 0; font-size: 13px; color: #285e61;\n }\n .error {\n background: #fed7d7; border-color: #fc8181; color: #742a2a;\n }\n .success {\n background: #d1fae5; border: 1px solid #10b981; color: #065f46;\n }\n .footer {\n margin-top: 20px; padding-top: 16px; border-top: 1px solid #e2e8f0;\n text-align: center; color: #718096;\n font-size: ${o?"11px":"12px"};\n }\n @media (max-width: 768px) {\n .category-services .service-item { padding: 8px 0; }\n .service-label { font-size: 13px; }\n }\n `,p.head.appendChild(u);class h{constructor(){this.presets=a,this.activePreset=null}applyPreset(e){const n=this.presets[e];if(!n)return!1;this.activePreset=e;const t=p.querySelectorAll(".service-checkbox");return t.forEach(e=>e.checked=!1),"all"===n.services?t.forEach(e=>e.checked=!0):n.services.forEach(e=>{const n=this.findServiceCheckbox(e);n&&(n.checked=!0)}),window.domainOSINTHub.updateCounter(),m(`✅ Applied preset: ${n.name}`,"success"),!0}findServiceCheckbox(e){const n=p.querySelectorAll(".service-checkbox");for(let t of n){const n=t.dataset.category,o=parseInt(t.dataset.serviceIndex);if(i[n].services[o].name===e)return t}return null}renderPresets(){const e=p.getElementById("presetsContainer");if(!e)return;e.querySelector(".presets-grid").innerHTML=Object.keys(this.presets).map(e=>{const n=this.presets[e],t="all"===n.services?"All":n.services.length;return`\n <div class="preset-card">\n <div class="preset-info">\n <div class="preset-name">${n.name}</div>\n <div class="preset-description">${n.description}</div>\n <div class="preset-meta">${t} services</div>\n </div>\n <div class="preset-actions">\n <button class="preset-btn btn-mini" data-preset="${e}">Apply</button>\n </div>\n </div>\n `}).join(""),e.querySelectorAll(".preset-btn").forEach(e=>{e.addEventListener("click",()=>{this.applyPreset(e.dataset.preset)})})}}class b{constructor(){this.searchTerm="",this.activeFilters=new Set}search(e){this.searchTerm=e.toLowerCase(),this.updateServiceVisibility()}toggleFilter(e,n){this.activeFilters.has(e)?(this.activeFilters.delete(e),n.classList.remove("active")):(this.activeFilters.add(e),n.classList.add("active")),this.updateServiceVisibility()}clearSearch(){this.searchTerm="",this.activeFilters.clear();const e=p.querySelector("#serviceSearch"),n=p.querySelectorAll(".filter-btn");e&&(e.value=""),n.forEach(e=>e.classList.remove("active")),this.updateServiceVisibility()}updateServiceVisibility(){p.querySelectorAll(".service-item").forEach(e=>{const n=e.querySelector(".service-checkbox"),t=e.querySelector(".service-label"),o=n.dataset.category,r=t.textContent.toLowerCase();let i=!0;this.searchTerm&&!r.includes(this.searchTerm)&&(i=!1),this.activeFilters.size>0&&!this.activeFilters.has(o)&&(i=!1),e.style.display=i?"flex":"none"}),Object.keys(i).forEach(e=>{const n=p.querySelector(`[data-category="${e}"]`);if(n){const e=n.querySelectorAll('.service-item[style*="flex"], .service-item:not([style])').length,t=n.previousElementSibling;t&&t.classList.contains("category-header")&&(t.style.display=e>0?"flex":"none")}})}}function g(n,t,o){const r=["=".repeat(60),"DOMAIN OSINT INVESTIGATION REPORT","=".repeat(60),"",`Target Domain: ${n}`,`Investigation Date: ${o}`,`Generated by: Domain OSINT Hub v${e}`,`Selected Services: ${t.length}`,"","INVESTIGATION URLS:","-".repeat(30),""];return t.forEach((e,t)=>{const o=e.url.replace(/{domain}/g,n);r.push(`${t+1}. ${e.name}`),r.push(` URL: ${o}`),e.longProcess&&r.push(" Note: This service may take longer to complete"),r.push("")}),r.push("INVESTIGATION CHECKLIST:","-".repeat(30),""),t.forEach(e=>{r.push(`[ ] ${e.name} - Analysis completed`)}),r.push("","FINDINGS SUMMARY:","-".repeat(30),"","[ ] Domain reputation check completed","[ ] DNS infrastructure analyzed","[ ] Certificate analysis completed","[ ] Historical data reviewed","[ ] Technology stack identified","[ ] Threat intelligence gathered","","INVESTIGATION NOTES:","-".repeat(30),"","(Add your investigation findings here)","","=".repeat(60),"End of Report","=".repeat(60)),r.join("\n")}function f(e){const n=s(p.getElementById("domainInput").value),t=p.querySelectorAll(".service-checkbox:checked");if(0===t.length)return void m("⚠️ Please select at least one service before exporting","error");let o=g(n,Array.from(t).map(e=>{const n=e.dataset.category,t=parseInt(e.dataset.serviceIndex);return{...i[n].services[t],category:n}}),(new Date).toISOString());const r=new Blob([o],{type:"text/plain"}),a=URL.createObjectURL(r),c=p.createElement("a");c.href=a,c.download=`osint-investigation-${n}-${(new Date).toISOString().split("T")[0]}.txt`,c.style.display="none",p.body.appendChild(c),c.click(),p.body.removeChild(c),URL.revokeObjectURL(a),m("✅ Text report exported successfully!","success")}const v=p.createElement("div");v.className="container",v.innerHTML=`\n <div class="header">\n <h1>🔍 Domain OSINT Hub v2.0</h1>\n <div class="subtitle">Professional Domain Reconnaissance Toolkit</div>\n </div>\n \n <div class="domain-section">\n <input type="text" class="domain-input" value="${l}" \n placeholder="Enter domain (e.g., example.com)" id="domainInput">\n </div>\n \n <div class="search-container">\n <div class="search-input-group">\n <input type="text" id="serviceSearch" class="search-input" \n placeholder="🔍 Search services..." autocomplete="off">\n <button class="search-clear" id="clearSearch" title="Clear search">×</button>\n </div>\n <div class="search-filters">\n <button class="filter-btn" data-filter="reputation">🛡️ Reputation</button>\n <button class="filter-btn" data-filter="dns">🌐 DNS</button>\n <button class="filter-btn" data-filter="certificates">🔐 Certificates</button>\n <button class="filter-btn" data-filter="intelligence">🔍 Intelligence</button>\n <button class="filter-btn" data-filter="whois">📋 WHOIS</button>\n <button class="filter-btn" data-filter="technology">⚙️ Technology</button>\n </div>\n </div>\n \n <div class="presets-section" id="presetsContainer">\n <div class="presets-header">\n <h3 class="section-title">⚡ Service Presets</h3>\n </div>\n <div class="presets-grid"></div>\n </div>\n \n <div class="button-group">\n <button class="btn btn-secondary" id="checkAllBtn">☑️ Check All</button>\n <button class="btn btn-secondary" id="uncheckAllBtn">☐ Uncheck All</button>\n <button class="btn btn-primary" id="helpBtn">❓ Help (F1)</button>\n </div>\n \n <div class="services-header">\n <h3 class="services-title">🔧 OSINT Services</h3>\n <span class="counter" id="selectedCounter">0 selected</span>\n </div>\n \n <div class="services-list" id="servicesList"></div>\n \n <div class="button-group">\n <button class="btn btn-success" id="openSelectedBtn" disabled>🚀 Open Selected Services</button>\n </div>\n \n <div class="export-section">\n <div class="section-title">📄 Export Investigation</div>\n <div class="export-buttons">\n <button class="btn-export" data-format="txt">📄 Text Report</button>\n </div>\n </div>\n \n <div id="statusDiv"></div>\n \n <div class="footer">\n Domain OSINT Hub v${e} | 30+ Services | Local Processing Only | CSP Compliant\n </div>\n `,p.body.appendChild(v);const x=new h,y=new b;window.domainOSINTHub.updateServices=function(){const e=p.getElementById("domainInput"),n=p.getElementById("servicesList"),t=p.getElementById("openSelectedBtn"),o=p.getElementById("statusDiv");if(!e||!n||!t)return;const r=s(e.value);if(n.innerHTML="",o.innerHTML="",!c(r))return m("⚠️ Please enter a valid domain (e.g., example.com)","error"),t.disabled=!0,void window.domainOSINTHub.updateCounter();Object.keys(i).forEach(e=>{const t=i[e],o=p.createElement("div");o.className="category-header",o.style.setProperty("--category-color",t.color),o.innerHTML=`\n <div class="category-info">\n <span class="category-icon">${t.icon}</span>\n <span class="category-name">${t.name}</span>\n <span class="category-count">${t.services.length} services</span>\n </div>\n <div class="category-controls">\n <button class="btn-mini category-toggle" data-category="${e}">Toggle All</button>\n </div>\n `,n.appendChild(o);const r=p.createElement("div");r.className="category-services",r.dataset.category=e,t.services.forEach((n,t)=>{const o=p.createElement("div");o.className="service-item";const i=p.createElement("input");i.type="checkbox",i.className="service-checkbox",i.id=`service_${e}_${t}`,i.dataset.category=e,i.dataset.serviceIndex=t;const a=p.createElement("label");a.className="service-label",a.setAttribute("for",i.id),a.textContent=n.name,n.longProcess&&(a.className+=" long-process",a.textContent+=" (long process)"),i.addEventListener("change",window.domainOSINTHub.updateCounter),o.appendChild(i),o.appendChild(a),r.appendChild(o)}),n.appendChild(r)});p.querySelectorAll(".category-toggle").forEach(e=>{e.addEventListener("click",n=>{n.preventDefault(),n.stopPropagation();const t=e.getAttribute("data-category"),o=e.closest(".category-header")?.nextElementSibling||p.querySelector(`.category-services[data-category="${t.replace(/["\\]/g,"\\$&")}"]`);window.domainOSINTHub.toggleCategory(t,o)},{capture:!0})}),p.title="Domain OSINT Hub v2.0 - "+r,window.domainOSINTHub.updateCounter()},window.domainOSINTHub.updateCounter=function(){const e=p.querySelectorAll(".service-checkbox:checked"),n=p.getElementById("selectedCounter"),t=p.getElementById("openSelectedBtn"),o=e.length;n&&(n.textContent=o+" selected"),t&&(t.disabled=0===o,t.textContent=o>0?`🚀 Open ${o} Selected Services`:"🚀 Open Selected Services")},window.domainOSINTHub.checkAll=function(){p.querySelectorAll(".service-checkbox").forEach(e=>e.checked=!0),window.domainOSINTHub.updateCounter()},window.domainOSINTHub.uncheckAll=function(){p.querySelectorAll(".service-checkbox").forEach(e=>e.checked=!1),window.domainOSINTHub.updateCounter()},window.domainOSINTHub.toggleCategory=function(e){console.log("Toggling category:",e);const n=p.querySelector(`[data-category="${e}"]`);if(!n)return void console.error("Category services not found for:",e);const t=n.querySelectorAll(".service-checkbox");if(0===t.length)return void console.error("No checkboxes found in category:",e);const o=Array.from(t).every(e=>e.checked);t.forEach(e=>{e.checked=!o}),window.domainOSINTHub.updateCounter();const r=i[e];m(`✅ ${o?"deselected":"selected"} all ${r.name} services`,"success")},window.domainOSINTHub.toggleCategory=function(e,n){const t=(e||"").replace(/["\\]/g,"\\$&"),o=n||p.querySelector(`.category-services[data-category="${t}"]`);if(!o)return console.error("Category services container not found for:",e),void m(`❌ Could not find "${e}" section`,"error");const r=o.querySelectorAll("input.service-checkbox");if(0===r.length)return console.error("No checkboxes in section:",e),void m(`❌ No services in "${e}"`,"error");const a=Array.from(r).every(e=>e.checked);r.forEach(e=>{e.checked=!a}),window.domainOSINTHub.updateCounter();const s=i[e];m(`✅ ${a?"deselected":"selected"} all ${s&&s.name||e} services`,"success")},window.domainOSINTHub.openSelectedServices=function(){const e=p.getElementById("domainInput"),n=p.querySelectorAll(".service-checkbox:checked"),o=p.getElementById("statusDiv");if(!e)return void m("❌ Error: Domain input not found","error");const r=s(e.value);if(0===n.length)return void m("⚠️ Please select at least one service to open","error");if(!c(r))return void m("⚠️ Please enter a valid domain","error");const a=Array.from(n).map(e=>{const n=e.dataset.category,t=parseInt(e.dataset.serviceIndex);return i[n].services[t]});o.innerHTML="";const l=m(`🚀 Opening ${a.length} services for ${r}...`);let d=0,u=0;a.forEach((e,n)=>{setTimeout(()=>{try{let t=e.url.replace(/{domain}/g,encodeURIComponent(r));window.open(t,"_blank","noopener,noreferrer")?d++:u++,n===a.length-1&&setTimeout(()=>{0===u?(l.textContent=`✅ Successfully opened ${d} services for ${r}`,l.className="status success"):(l.textContent=`⚠️ Opened ${d}/${a.length} services (${u} blocked by popup blocker)`,l.className="status error")},100)}catch(n){u++,console.error("Error opening service:",e.name,n)}},n*t)})};const w=p.getElementById("domainInput"),S=p.getElementById("serviceSearch"),I=p.getElementById("clearSearch"),k=p.querySelectorAll(".filter-btn"),T=p.getElementById("checkAllBtn"),N=p.getElementById("uncheckAllBtn"),E=p.getElementById("helpBtn"),O=p.getElementById("openSelectedBtn"),C=p.querySelectorAll(".btn-export");w.addEventListener("input",window.domainOSINTHub.updateServices),w.addEventListener("paste",()=>setTimeout(window.domainOSINTHub.updateServices,100)),S.addEventListener("input",e=>y.search(e.target.value)),I.addEventListener("click",()=>y.clearSearch()),k.forEach(e=>{e.addEventListener("click",()=>y.toggleFilter(e.dataset.filter,e))}),T.addEventListener("click",window.domainOSINTHub.checkAll),N.addEventListener("click",window.domainOSINTHub.uncheckAll),E.addEventListener("click",()=>{alert('Domain OSINT Hub v2.0 Help:\n\n⌨️ Keyboard Shortcuts:\n• Ctrl+A: Check all services\n• Ctrl+D: Uncheck all services\n• 1-6: Apply presets 1-6\n• F1: Show this help\n• Esc: Close window\n\n🔍 Features:\n• Search services by name\n• Filter by category\n• Apply presets for common tasks\n• Export investigation reports\n• Mobile-optimized interface\n\n⚡ Quick Presets:\n1. Quick Scan\n2. Full Investigation\n3. Reputation Check\n4. Infrastructure Analysis\n5. Passive Reconnaissance\n6. Threat Hunting\n\n🔧 Toggle All Buttons:\n• Click "Toggle All" next to any category header\n• Toggles all services in that category on/off')}),O.addEventListener("click",window.domainOSINTHub.openSelectedServices),C.forEach(e=>{e.addEventListener("click",()=>f(e.dataset.format))}),p.addEventListener("keydown",e=>{const n=e.ctrlKey||e.metaKey;if(n&&"a"===e.key)e.preventDefault(),window.domainOSINTHub.checkAll();else if(n&&"d"===e.key)e.preventDefault(),window.domainOSINTHub.uncheckAll();else if(n&&"Enter"===e.key)e.preventDefault(),window.domainOSINTHub.openSelectedServices();else if("F1"===e.key)e.preventDefault(),E.click();else if("Escape"===e.key)try{window.domainOSINTHub.close()}catch(e){}else if(!/^[1-6]$/.test(e.key)||n||e.altKey)"Enter"===e.key&&e.target===w&&(e.preventDefault(),window.domainOSINTHub.updateServices());else{const n=Object.keys(a),t=parseInt(e.key)-1;n[t]&&x.applyPreset(n[t])}}),window.domainOSINTHub.presetManager=x,window.domainOSINTHub.serviceSearch=y,window.domainOSINTHub.updateServices(),x.renderPresets(),window.domainOSINTHub.focus(),w.focus(),w.select()}catch(D){if(console.error("Domain OSINT Hub Error:",D),alert("Domain OSINT Hub Error: "+D.message+"\n\nPlease try again or check browser console for details."),window.domainOSINTHub){try{window.domainOSINTHub.close()}catch(L){}window.domainOSINTHub=null}}}(),domain;">
Domain OSINT
</a>
<button class="copy-btn" onclick="copyBookmarkletCode(this)">Copy Code</button>
</div>
</div>
<div class="bookmarklet-description">
Professional domain reconnaissance toolkit with 30+ OSINT services, preset investigation workflows, and exportable reports.
</div>
<ul class="features">
<li>30+ OSINT services across 6 categories (reputation, DNS, WHOIS, certificates, intelligence, technology)</li>
<li>Preset investigation workflows: Quick Scan, Full Investigation, Threat Hunting</li>
<li>Service search and category filtering</li>
<li>Text report export for documentation</li>
<li>Keyboard shortcuts for power users</li>
</ul>
</div>
<div class="bookmarklet">
<div class="bookmarklet-header">
<div class="bookmarklet-title">🚀 Multi-URL Opener</div>
<div class="button-group">
<a href="javascript:void(0)"
class="bookmarklet-link"
draggable="true"
data-bookmarklet-name="Multi-URL Opener"
title="Drag this button to your bookmarks bar"
data-bookmarklet-code="javascript:!function(){"use strict";const e="1.0.1",n=250,t="__MultiURLOpener__";if(window[t])window[t].focus();else try{const o=function(){const t=window.open("","multiURLOpener","width=600,height=500,scrollbars=yes,resizable=yes");if(!t)return alert("Popup blocked! Please allow popups for this site and try again."),null;const o=t.document;for(;o.documentElement.firstChild;)o.documentElement.removeChild(o.documentElement.firstChild);const r=o.createElement("head"),a=o.createElement("body"),i=o.createElement("title");i.textContent="Multi-URL Opener",r.appendChild(i);const l=o.createElement("meta");l.setAttribute("charset","utf-8"),r.appendChild(l),r.appendChild(function(e){const n=e.createElement("style");return n.textContent="\n * {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n \n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: #f8fafc;\n color: #1a202c;\n line-height: 1.5;\n }\n \n .container {\n max-width: 100%;\n padding: 20px;\n min-height: 100vh;\n }\n \n .header {\n background: #3498db;\n color: white;\n padding: 15px 20px;\n margin: -20px -20px 20px -20px;\n border-radius: 0 0 8px 8px;\n }\n \n .header h1 {\n font-size: 18px;\n font-weight: 600;\n }\n \n .form-group {\n margin-bottom: 16px;\n }\n \n label {\n display: block;\n margin-bottom: 6px;\n font-weight: 500;\n color: #374151;\n }\n \n textarea {\n width: 100%;\n height: 200px;\n padding: 12px;\n border: 2px solid #e5e7eb;\n border-radius: 6px;\n font-family: 'Courier New', monospace;\n font-size: 12px;\n resize: vertical;\n background: white;\n }\n \n textarea:focus {\n outline: none;\n border-color: #3498db;\n box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);\n }\n \n .url-info {\n background: #f1f5f9;\n border: 1px solid #cbd5e1;\n border-radius: 6px;\n padding: 12px;\n margin-bottom: 16px;\n font-size: 14px;\n }\n \n .url-count {\n font-weight: 600;\n color: #059669;\n }\n \n .actions {\n display: flex;\n gap: 12px;\n align-items: center;\n }\n \n button {\n padding: 12px 24px;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n }\n \n .btn-primary {\n background: #10b981;\n color: white;\n }\n \n .btn-primary:hover:not(:disabled) {\n background: #059669;\n }\n \n .btn-secondary {\n background: #6b7280;\n color: white;\n }\n \n .btn-secondary:hover {\n background: #4b5563;\n }\n \n button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n \n .help {\n background: #fef3c7;\n border: 1px solid #f59e0b;\n border-radius: 6px;\n padding: 12px;\n margin-top: 16px;\n font-size: 13px;\n color: #92400e;\n }\n \n .help strong {\n color: #78350f;\n }\n \n .url-preview {\n margin-top: 6px;\n font-size: 12px;\n color: #6b7280;\n }\n ",n}(o));const d=o.createElement("div");d.className="container";const s=o.createElement("div");s.className="header";const c=o.createElement("h1");c.textContent=`🚀 Multi-URL Opener v${e}`,s.appendChild(c),d.appendChild(s);const p=o.createElement("div");p.className="form-group";const m=o.createElement("label");m.textContent="Paste URLs (any format):",m.setAttribute("for","urlInput"),p.appendChild(m);const u=o.createElement("textarea");u.id="urlInput",u.placeholder="Paste your URLs here...\n\nSupports:\n• One URL per line\n• Comma-separated URLs\n• Space-separated URLs\n• Mixed formats\n\nExamples:\nexample.com\nhttps://google.com\nsite1.com, site2.com\nwww.github.com stackoverflow.com",p.appendChild(u),d.appendChild(p);const h=o.createElement("div");h.className="url-info",h.id="urlInfo";const b=o.createElement("span");b.className="url-count",b.id="urlCount",b.textContent="0",h.appendChild(b);const f=o.createElement("span");f.textContent=" valid URLs detected",h.appendChild(f);const x=o.createElement("div");x.className="url-preview",x.id="urlPreview",x.textContent="Enter URLs above to see preview",h.appendChild(x),d.appendChild(h);const g=o.createElement("div");g.className="actions";const C=o.createElement("button");C.id="openBtn",C.className="btn-primary",C.textContent="Open All URLs",C.disabled=!0,g.appendChild(C);const w=o.createElement("button");w.id="clearBtn",w.className="btn-secondary",w.textContent="Clear",g.appendChild(w);const E=o.createElement("button");E.id="closeBtn",E.className="btn-secondary",E.textContent="Close",g.appendChild(E),d.appendChild(g);const v=o.createElement("div");v.className="help";const y=o.createElement("strong");y.textContent="💡 Pro Tips:",v.appendChild(y);const L=o.createElement("br");v.appendChild(L);const k=o.createTextNode(`• URLs are opened with ${n}ms delays to prevent popup blocking`);v.appendChild(k);const R=o.createElement("br");v.appendChild(R);const U=o.createTextNode("• Missing https:// protocols are automatically added");v.appendChild(U);const N=o.createElement("br");v.appendChild(N);const $=o.createTextNode("• Duplicate URLs are automatically filtered");v.appendChild($);const T=o.createElement("br");v.appendChild(T);const z=o.createTextNode("• Perfect for OSINT research and bulk investigations");v.appendChild(z),d.appendChild(v),a.appendChild(d),o.documentElement.appendChild(r),o.documentElement.appendChild(a);let O=[];function S(){if(O=function(e){if(!e||"string"!=typeof e)return[];const n=e.split(/[\n\r,;|\t]+|(?:\s{2,})/).map(e=>e.trim()).filter(e=>e.length>0),t=new Set;return n.forEach(e=>{const n=e.replace(/^["'\[<]|["'\]>]$/g,"");if(/^(?:https?:\/\/)?(?:[\w-]+\.)+[\w-]+(?:\/[^\s]*)?$/i.test(n)){const e=n.startsWith("http")?n:`https://${n}`;try{new URL(e).hostname&&t.add(e)}catch(e){}}}),Array.from(t)}(u.value),b.textContent=O.length.toString(),O.length>0){C.disabled=!1;const e=O.slice(0,3).join(", ");x.textContent=O.length>3?`${e}... and ${O.length-3} more`:e}else C.disabled=!0,x.textContent="Enter URLs above to see preview"}return u.addEventListener("input",S),u.addEventListener("paste",()=>{setTimeout(S,100)}),C.addEventListener("click",()=>{0!==O.length&&function(e){if(!e||0===e.length)return void alert("No valid URLs found to open.");if(e.length>50&&!confirm(`You're about to open ${e.length} URLs. This may impact browser performance. Continue?`))return;let t=0;e.forEach((e,o)=>{setTimeout(()=>{try{window.open(e,"_blank","noopener,noreferrer"),t++}catch(n){console.warn(`Failed to open URL: ${e}`,n)}},o*n)}),setTimeout(()=>{alert(`Successfully opened ${t} of ${e.length} URLs.`)},e.length*n+500)}(O)}),w.addEventListener("click",()=>{u.value="",S(),u.focus()}),E.addEventListener("click",()=>{t.close()}),o.addEventListener("keydown",e=>{e.ctrlKey&&"Enter"===e.key&&!C.disabled&&C.click(),"Escape"===e.key&&t.close()}),u.focus(),t}();if(o){window[t]=o;const e=setInterval(()=>{o.closed&&(clearInterval(e),delete window[t])},1e3)}}catch(e){console.error("Multi-URL Opener Error:",e),alert("Error: "+e.message),delete window[t]}}();">
Multi-URL
</a>
<button class="copy-btn" onclick="copyBookmarkletCode(this)">Copy Code</button>
</div>
</div>
<div class="bookmarklet-description">
Paste a list of URLs and open them all at once with smart detection and protocol correction. Built for OSINT workflows.
</div>
<ul class="features">
<li>Smart URL detection from pasted text</li>
<li>Automatic protocol correction (adds https:// if missing)</li>
<li>Batch opening with configurable delay</li>
<li>Duplicate URL filtering</li>
<li>Works with any URL format</li>
</ul>
</div>
<div class="bookmarklet">
<div class="bookmarklet-header">
<div class="bookmarklet-title">🕵️ Username Generator</div>
<div class="button-group">
<a href="javascript:void(0)"
class="bookmarklet-link"
draggable="true"
data-bookmarklet-name="Username Generator"
title="Drag this button to your bookmarks bar"
data-bookmarklet-code="javascript:!function(){"use strict";const e={version:"1.0.0",name:"Username Generator",popupId:"osint-username-gen-"+Date.now()};if(window.__UsernameGenPopup__)try{return void window.__UsernameGenPopup__.focus()}catch(e){}const t=window.open("about:blank",e.popupId,"width=850,height=700,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no,status=no");if(!t)return void alert("Popup blocked! Please allow popups for this site and try again.");t.document.write("<!DOCTYPE html><html><head> <title>"+e.name+'</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif; background: #0f172a; color: #e2e8f0; padding: 20px; min-height: 100vh; } .container { max-width: 800px; margin: 0 auto; background: #1e293b; border-radius: 12px; border: 1px solid #334155; overflow: hidden; } .header { background: #0f172a; padding: 16px 20px; border-bottom: 1px solid #334155; display: flex; justify-content: space-between; align-items: center; } .title { font-size: 18px; font-weight: 600; color: #f1f5f9; } .version { font-size: 12px; color: #64748b; background: #374151; padding: 2px 8px; border-radius: 4px; } .content { padding: 24px; } .input-group { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 20px; } .input-full { grid-column: 1 / -1; } .separator { grid-column: 1 / -1; text-align: center; color: #64748b; margin: 12px 0; position: relative; } .separator::before { content: ""; position: absolute; top: 50%; left: 0; right: 0; height: 1px; background: #334155; } .separator span { background: #1e293b; padding: 0 12px; font-size: 12px; font-weight: 500; } label { display: flex; flex-direction: column; gap: 6px; font-size: 13px; font-weight: 500; color: #cbd5e1; } input, textarea { padding: 10px 12px; background: #0f172a; border: 1px solid #475569; border-radius: 8px; color: #f1f5f9; font-size: 13px; font-family: inherit; } input:focus, textarea:focus { outline: none; border-color: #0ea5e9; box-shadow: 0 0 0 3px rgba(14, 165, 233, 0.1); } .checkbox-group { display: flex; gap: 20px; margin: 16px 0; align-items: center; } .checkbox-item { display: flex; align-items: center; gap: 8px; cursor: pointer; font-size: 13px; } input[type="checkbox"] { width: 16px; height: 16px; cursor: pointer; } .button-group { display: flex; gap: 12px; margin: 20px 0; align-items: center; } button { padding: 10px 16px; border: none; border-radius: 8px; font-size: 13px; font-weight: 500; cursor: pointer; font-family: inherit; transition: all 0.2s; } .btn-primary { background: #0ea5e9; color: white; } .btn-primary:hover { background: #0284c7; } .btn-secondary { background: #475569; color: white; } .btn-secondary:hover { background: #64748b; } .btn-secondary:disabled { background: #334155; color: #64748b; cursor: not-allowed; } .status { margin-left: auto; font-size: 12px; color: #64748b; } .output-section { margin-top: 20px; border-top: 1px solid #334155; padding-top: 20px; } .meta { font-size: 12px; color: #64748b; margin-bottom: 10px; } textarea { width: 100%; height: 200px; resize: vertical; font-family: ui-monospace, "Cascadia Code", Consolas, monospace; line-height: 1.4; white-space: pre; } .help-text { font-size: 11px; color: #64748b; margin-top: 4px; } </style></head><body> <div class="container"> <div class="header"> <div class="title">'+e.name+'</div> <div class="version">v'+e.version+'</div> </div> <div class="content"> <div class="input-group"> <label> First name (optional) <input type="text" id="firstName" placeholder="John"> <div class="help-text">Leave empty if unknown</div> </label> <label> Last name (optional) <input type="text" id="lastName" placeholder="Doe"> <div class="help-text">Leave empty if unknown</div> </label> <div class="separator"><span>OR</span></div> <label class="input-full"> Existing username to expand <input type="text" id="existingUsername" placeholder="johndoe123, j.doe, john_d"> <div class="help-text">Parse and generate variations from existing username</div> </label> <label> Separators (comma-separated) <input type="text" id="separators" value=".,_,-"> <div class="help-text">Characters to use between name parts</div> </label> <label> Prefix (optional) <input type="text" id="prefix" placeholder="user, admin, etc."> </label> <label> Suffix (optional) <input type="text" id="suffix" placeholder="corp, dev, etc."> </label> </div> <div class="checkbox-group"> <label class="checkbox-item"> <input type="checkbox" id="includeNumbers"> Include numbers (1, 123, 2024, etc.) </label> <label class="checkbox-item"> <input type="checkbox" id="caseVariations" checked> Case variations (lower, UPPER, Title) </label> </div> <div class="button-group"> <button class="btn-primary" id="generateBtn">Generate</button> <button class="btn-secondary" id="copyBtn" disabled>Copy All</button> <button class="btn-secondary" id="downloadBtn" disabled>Download .txt</button> <div class="status" id="status">Ready</div> </div> <div class="output-section"> <div class="meta" id="meta">Enter information above and click Generate</div> <textarea id="output" placeholder="Generated usernames will appear here..." readonly></textarea> </div> </div> </div> <script> // All JavaScript functions defined above are available here function sanitize(str) { return (typeof str === "string" ? str : "").replace(/[^a-zA-Z0-9 _.-]/g, "").trim(); } function capitalize(str) { return str ? str.charAt(0).toUpperCase() + str.slice(1).toLowerCase() : str; } function parseUsername(username) { var clean = username.toLowerCase().replace(/[^a-z]/g, ""); var parsed = { original: username, base: clean, possibleFirst: "", possibleLast: "", numbers: username.match(/\\d+/g) || [], separators: username.match(/[._-]/g) || [] }; var parts = username.split(/[._-]/); if (parts.length === 2) { parsed.possibleFirst = sanitize(parts[0]); parsed.possibleLast = sanitize(parts[1]); } else if (clean.length >= 4) { var mid = Math.floor(clean.length / 2); parsed.possibleFirst = clean.substring(0, mid); parsed.possibleLast = clean.substring(mid); } return parsed; } function addVariation(set, base, prefix, suffix, caseVariations) { if (!base) return; var full = (prefix || "") + base + (suffix || ""); if (full.length < 1 || full.length > 50) return; if (caseVariations) { set.add(full.toLowerCase()); set.add(full.toUpperCase()); set.add(capitalize(full)); if (full !== full.toLowerCase()) set.add(full); } else { set.add(full.toLowerCase()); } } function removePrefix(str, prefix) { if (!prefix) return str; if (str.toLowerCase().startsWith(prefix.toLowerCase())) { return str.substring(prefix.length); } return str; } function removeSuffix(str, suffix) { if (!suffix) return str; if (str.toLowerCase().endsWith(suffix.toLowerCase())) { return str.substring(0, str.length - suffix.length); } return str; } function generateUsernames(opts) { var usernames = new Set(); var f = sanitize(opts.firstName); var l = sanitize(opts.lastName); var parsed = null; if (opts.existingUsername && opts.existingUsername.trim()) { parsed = parseUsername(sanitize(opts.existingUsername)); if (!f && !l) { f = parsed.possibleFirst; l = parsed.possibleLast; } addVariation(usernames, parsed.original, opts.prefix, opts.suffix, opts.caseVariations); addVariation(usernames, parsed.base, opts.prefix, opts.suffix, opts.caseVariations); } if (f && !l) { l = ""; } else if (!f && l) { f = l; l = ""; } if (f) { var fi = f.charAt(0); var f3 = f.substring(0, Math.min(3, f.length)); var f4 = f.substring(0, Math.min(4, f.length)); addVariation(usernames, f, opts.prefix, opts.suffix, opts.caseVariations); addVariation(usernames, f3, opts.prefix, opts.suffix, opts.caseVariations); addVariation(usernames, f4, opts.prefix, opts.suffix, opts.caseVariations); addVariation(usernames, fi, opts.prefix, opts.suffix, opts.caseVariations); if (l) { var li = l.charAt(0); var l3 = l.substring(0, Math.min(3, l.length)); var l4 = l.substring(0, Math.min(4, l.length)); var combinations = [ f + l, l + f, fi + l, l + fi, f + li, li + f, f3 + l3, l3 + f3, f4 + l4, l4 + f4, fi + li, li + fi, l ]; combinations.forEach(function(combo) { addVariation(usernames, combo, opts.prefix, opts.suffix, opts.caseVariations); }); var seps = opts.separators.split(",").map(function(s) { return s.trim(); }).filter(Boolean); seps.forEach(function(sep) { [ f + sep + l, l + sep + f, f + sep + li, l + sep + fi, fi + sep + l, li + sep + f, f3 + sep + l3, l3 + sep + f3, fi + sep + li, li + sep + fi ].forEach(function(combo) { addVariation(usernames, combo, opts.prefix, opts.suffix, opts.caseVariations); }); }); } } if (opts.includeNumbers) { var numbers = ["1", "01", "12", "123", "1234", "21", "2023", "2024", "2025"]; if (parsed && parsed.numbers.length > 0) { numbers.push.apply(numbers, parsed.numbers); } var currentUsernames = Array.from(usernames); currentUsernames.forEach(function(username) { var base = username; base = removePrefix(base, opts.prefix); base = removeSuffix(base, opts.suffix); numbers.forEach(function(num) { addVariation(usernames, base, opts.prefix, (opts.suffix || "") + num, opts.caseVariations); addVariation(usernames, base, (opts.prefix || "") + num, opts.suffix, opts.caseVariations); }); }); } return Array.from(usernames).filter(function(u) { return u.length > 0; }).sort(); } function downloadFile(filename, text) { var blob = new Blob([text], { type: "text/plain" }); var url = URL.createObjectURL(blob); var a = document.createElement("a"); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); a.remove(); URL.revokeObjectURL(url); } var elements = { firstName: document.getElementById("firstName"), lastName: document.getElementById("lastName"), existingUsername: document.getElementById("existingUsername"), separators: document.getElementById("separators"), prefix: document.getElementById("prefix"), suffix: document.getElementById("suffix"), includeNumbers: document.getElementById("includeNumbers"), caseVariations: document.getElementById("caseVariations"), generateBtn: document.getElementById("generateBtn"), copyBtn: document.getElementById("copyBtn"), downloadBtn: document.getElementById("downloadBtn"), status: document.getElementById("status"), meta: document.getElementById("meta"), output: document.getElementById("output") }; elements.generateBtn.onclick = function() { elements.status.textContent = "Generating..."; elements.copyBtn.disabled = true; elements.downloadBtn.disabled = true; var opts = { firstName: elements.firstName.value, lastName: elements.lastName.value, existingUsername: elements.existingUsername.value, separators: elements.separators.value || ".,_,-", prefix: elements.prefix.value, suffix: elements.suffix.value, includeNumbers: elements.includeNumbers.checked, caseVariations: elements.caseVariations.checked }; if (!opts.firstName && !opts.lastName && !opts.existingUsername) { elements.status.textContent = "Input required"; elements.meta.textContent = "❌ Please provide at least one: first name, last name, or existing username"; return; } try { var usernames = generateUsernames(opts); elements.output.value = usernames.join("\\n"); var inputDesc = opts.existingUsername ? "from username \\"" + opts.existingUsername + "\\"" : "for " + (opts.firstName || "?") + " " + (opts.lastName || "?"); elements.meta.textContent = "Generated " + inputDesc + " • Total: " + usernames.length + " variations"; elements.status.textContent = "Complete ✓"; elements.copyBtn.disabled = false; elements.downloadBtn.disabled = false; } catch (error) { elements.status.textContent = "Error occurred"; elements.meta.textContent = "❌ Generation failed. Please check inputs and try again."; } }; elements.copyBtn.onclick = function() { elements.output.select(); elements.output.setSelectionRange(0, 99999); try { document.execCommand("copy"); elements.status.textContent = "Copied ✓"; setTimeout(function() { elements.status.textContent = "Complete ✓"; }, 2000); } catch (error) { elements.status.textContent = "Copy failed"; } }; elements.downloadBtn.onclick = function() { var timestamp = new Date().toISOString(); var usernames = elements.output.value.split("\\n").filter(Boolean); var inputInfo = elements.existingUsername.value ? "Expanded from: " + elements.existingUsername.value : "Names: " + (elements.firstName.value || "?") + " " + (elements.lastName.value || "?"); var header = "# Username Variations\\n# " + inputInfo + "\\n# Generated: " + timestamp + "\\n# Total: " + usernames.length + "\\n# Generator: '+e.name+" v"+e.version+'\\n#\\n# Usage: OSINT, social media search, account discovery\\n\\n"; var filename = "usernames_" + Date.now() + ".txt"; downloadFile(filename, header + usernames.join("\\n") + "\\n"); elements.status.textContent = "Downloaded ✓"; setTimeout(function() { elements.status.textContent = "Complete ✓"; }, 2000); }; elements.firstName.focus(); elements.existingUsername.oninput = function() { if (this.value.trim()) { elements.firstName.style.opacity = "0.5"; elements.lastName.style.opacity = "0.5"; } else { elements.firstName.style.opacity = "1"; elements.lastName.style.opacity = "1"; } }; [elements.firstName, elements.lastName].forEach(function(input) { input.oninput = function() { if (elements.firstName.value.trim() || elements.lastName.value.trim()) { elements.existingUsername.style.opacity = "0.5"; } else { elements.existingUsername.style.opacity = "1"; } }; }); <\/script></body></html>'),t.document.close(),window.__UsernameGenPopup__=t;const a=setInterval(()=>{t.closed&&(clearInterval(a),delete window.__UsernameGenPopup__)},1e3)}();">
Username Gen
</a>
<button class="copy-btn" onclick="copyBookmarkletCode(this)">Copy Code</button>
</div>
</div>
<div class="bookmarklet-description">
Generate comprehensive username variations from a name for cross-platform OSINT searches and social media investigations.
</div>
<ul class="features">
<li>Flexible input: first/last name, full name, or username</li>
<li>500+ username variations with smart patterns</li>
<li>Common separators and number suffixes</li>
<li>One-click copy for individual usernames</li>
<li>Export full list as text</li>
</ul>
</div>
<div class="bookmarklet">
<div class="bookmarklet-header">
<div class="bookmarklet-title">🚢 Vessel Tracker</div>
<div class="button-group">
<a href="javascript:void(0)"
class="bookmarklet-link"
draggable="true"
data-bookmarklet-name="Vessel Tracker"
title="Drag this button to your bookmarks bar"
data-bookmarklet-code="javascript:!function(){"use strict";const e="width=950,height=750,resizable,scrollbars";if(window.vesselTrackerRunning)alert("Vessel Tracker is already running!");else{window.vesselTrackerRunning=!0;try{function t(e){const t=String(e).replace(/[^0-9]/g,"");if(7!==t.length)return!1;const n=[];for(let e=0;e<7;e++)n[e]=parseInt(t.charAt(e),10);const i=[7,6,5,4,3,2];let o=0;o+=n[0]*i[0],o+=n[1]*i[1],o+=n[2]*i[2],o+=n[3]*i[3],o+=n[4]*i[4],o+=n[5]*i[5];return o-10*Math.floor(o/10)===n[6]}function n(e,n){const i=String(e||"").replace(/[^0-9]/g,"");if(7!==i.length)return{valid:!1,reason:"Must be exactly 7 digits",canBypass:!1};return t(i)?{valid:!0,reason:"Valid IMO with correct checksum"}:n?{valid:!0,reason:"Format valid (checksum bypassed)",bypassed:!0}:{valid:!1,reason:"Invalid checksum (click Force Search to bypass)",canBypass:!0}}function i(e){return 9===String(e||"").replace(/[^0-9]/g,"").length}function o(e){const t=String(e).replace(/[^0-9]/g,"");return{MarineTraffic:"https://www.marinevesseltraffic.com/vessels?page=1&vessel="+t,VesselFinder:"https://www.vesselfinder.com/vessels/details/"+t,MyShipTracking:"https://www.myshiptracking.com/vessels/details/"+t,BalticShipping:"https://www.balticshipping.com/vessel/imo/"+t,VesselTracker:"https://www.vesseltracker.com/en/Ships/"+t+".html"}}function a(e){const t=String(e).replace(/[^0-9]/g,"");return{MarineTraffic:"https://www.marinevesseltraffic.com/vessels?page=1&vessel="+t,VesselFinder:"https://www.vesselfinder.com/vessels?name="+t,MyShipTracking:"https://www.myshiptracking.com/?search="+t,MarineVesselTraffic:"https://www.marinevesseltraffic.com/vessels?mmsi="+t}}function r(e){const t=encodeURIComponent(e);return{VesselFinder:"https://www.vesselfinder.com/vessels?name="+t,MarineTraffic:"https://www.marinetraffic.com/en/ais/index/search/all/keyword:"+t,MyShipTracking:"https://www.myshiptracking.com/?search="+t}}function s(e){const t=Object.values(e);let n=0;t.forEach(function(e,t){setTimeout(function(){try{window.open(e,"_blank"),n+=1}catch(t){console.warn("Failed to open:",e)}},100*t)}),setTimeout(function(){alert("Opened "+n+" of "+t.length+" links")},100*t.length+500)}function l(e){return new Promise(function(t,n){if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(e).then(t).catch(n);else{const i=document.createElement("textarea");i.value=e,i.style.position="fixed",i.style.opacity="0",document.body.appendChild(i),i.select();try{const e=document.execCommand("copy");document.body.removeChild(i),e?t():n(new Error("Copy command failed"))}catch(e){document.body.removeChild(i),n(e)}}})}function c(e){function t(e){return null==e&&(e=""),-1===(e=String(e)).indexOf(",")&&-1===e.indexOf('"')&&-1===e.indexOf("\n")||(e='"'+e.replace(/"/g,'""')+'"'),e}return"Query Type,Query Value,Provider,URL\n"+e.map(function(e){return[e.query_type,e.query_value,e.provider,e.url].map(t).join(",")}).join("\n")}function d(e,t,n){const i=[];for(const o in n)n.hasOwnProperty(o)&&i.push({query_type:e,query_value:t,provider:o,url:n[o]});return i}function m(e,t){try{const n=new Blob([t],{type:"text/csv;charset=utf-8;"}),i=document.createElement("a"),o=URL.createObjectURL(n);i.setAttribute("href",o),i.setAttribute("download",e),i.style.visibility="hidden",document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(o)}catch(e){console.error("CSV download failed:",e),alert("CSV download failed. Check console for details.")}}const u=window.open("","vessel_tracker_popup",e);if(!u)return void alert("Popup blocked. Please allow popups for this site and try again.");u.document.title="Vessel Tracker";const p=u.document.createElement("head"),v=u.document.createElement("style");v.textContent="body{font-family:system-ui,sans-serif;background:#0f172a;color:#e5e7eb;margin:0;padding:16px;line-height:1.5}h2{margin-top:0;color:#60a5fa}h3{color:#93c5fd;margin-bottom:8px}input{padding:8px 12px;border-radius:6px;border:1px solid #334155;background:#111827;color:#e5e7eb;width:100%;box-sizing:border-box;margin-bottom:8px}input:focus{outline:none;border-color:#60a5fa;box-shadow:0 0 0 2px rgba(96,165,250,0.2)}.section{margin-bottom:20px;padding:16px;border:1px solid #334155;border-radius:8px;background:#1e293b}.buttons{margin-top:12px;display:flex;flex-wrap:wrap;gap:8px}button{padding:8px 16px;border-radius:6px;border:1px solid #334155;background:#374151;color:#e5e7eb;cursor:pointer;font-size:14px;transition:background-color 0.2s}button:hover{background:#4b5563}button.primary{background:#1d4ed8;border-color:#1d4ed8}button.primary:hover{background:#1e40af}button.force{background:#dc2626;border-color:#dc2626}button.force:hover{background:#b91c1c}.links{margin-top:12px;max-height:200px;overflow-y:auto}.links a{color:#93c5fd;display:block;word-break:break-all;margin:4px 0;padding:4px 8px;border-radius:4px;background:#0f172a;text-decoration:none}.links a:hover{background:#1e293b;color:#bfdbfe}.validation-msg{font-size:12px;color:#ef4444;margin-top:4px}.validation-msg.valid{color:#10b981}.validation-msg.warning{color:#f59e0b}",p.appendChild(v),u.document.head.appendChild(p);const f=u.document.createElement("body"),g=u.document.createElement("h2");g.textContent="Vessel Tracker",f.appendChild(g);const b=u.document.createElement("div");b.className="section",b.innerHTML='<h3>Search by IMO Number</h3><input id="imoInput" type="text" placeholder="Enter IMO number (7 digits)" maxlength="10" /><div id="imoValidation" class="validation-msg"></div><div class="buttons"><button id="imoOpen" class="primary">Open All Links</button><button id="imoForce" class="force" style="display:none">Force Search</button><button id="imoCopy">Copy All Links</button><button id="imoCSV">Download CSV</button></div><div id="imoLinks" class="links"></div>',f.appendChild(b);const h=u.document.createElement("div");h.className="section",h.innerHTML='<h3>Search by MMSI Number</h3><input id="mmsiInput" type="text" placeholder="Enter MMSI number (9 digits)" maxlength="12" /><div id="mmsiValidation" class="validation-msg"></div><div class="buttons"><button id="mmsiOpen" class="primary">Open All Links</button><button id="mmsiCopy">Copy All Links</button><button id="mmsiCSV">Download CSV</button></div><div id="mmsiLinks" class="links"></div>',f.appendChild(h);const y=u.document.createElement("div");y.className="section",y.innerHTML='<h3>Search by Vessel Name</h3><input id="nameInput" type="text" placeholder="Enter vessel name (minimum 3 characters)" /><div id="nameValidation" class="validation-msg"></div><div class="buttons"><button id="nameOpen" class="primary">Open All Links</button><button id="nameCopy">Copy All Links</button><button id="nameCSV">Download CSV</button></div><div id="nameLinks" class="links"></div>',f.appendChild(y),u.document.body.appendChild(f);const k=u.document;function w(e){const t=k.getElementById("imoInput"),i=k.getElementById("imoValidation"),a=k.getElementById("imoLinks"),r=k.getElementById("imoForce"),s=t.value.trim();if(a.textContent="",r.style.display="none",!s)return void(i.textContent="");const l=n(s,e);if(!l.valid)return i.textContent=l.reason,i.className="validation-msg",void(l.canBypass&&(r.style.display="inline-block"));let c=l.reason;l.bypassed?(i.className="validation-msg warning",c+=" ⚠️"):(i.className="validation-msg valid",c+=" ✓"),i.textContent=c;const d=o(s);for(const e in d){const t=k.createElement("a");t.href=d[e],t.target="_blank",t.textContent=e+": "+d[e],a.appendChild(t)}}function I(){const e=k.getElementById("mmsiInput"),t=k.getElementById("mmsiValidation"),n=k.getElementById("mmsiLinks"),o=e.value.trim();if(n.innerHTML="",!o)return void(t.textContent="");if(!i(o))return t.textContent="Invalid MMSI number (must be exactly 9 digits)",void(t.className="validation-msg");t.textContent="Valid MMSI number ✓",t.className="validation-msg valid";const r=a(o);for(const e in r){const t=k.createElement("a");t.href=r[e],t.target="_blank",t.textContent=e+": "+r[e],n.appendChild(t)}}function x(){const e=k.getElementById("nameInput"),t=k.getElementById("nameValidation"),n=k.getElementById("nameLinks"),i=e.value.trim();if(n.innerHTML="",!i)return void(t.textContent="");if(i.length<3)return t.textContent="Vessel name must be at least 3 characters",void(t.className="validation-msg");t.textContent="Ready to search ✓",t.className="validation-msg valid";const o=r(i);for(const e in o){const t=k.createElement("a");t.href=o[e],t.target="_blank",t.textContent=e+": "+o[e],n.appendChild(t)}}function E(e,t){return n(e,t).valid}k.getElementById("imoInput").addEventListener("input",function(){w()}),k.getElementById("mmsiInput").addEventListener("input",I),k.getElementById("nameInput").addEventListener("input",x),k.getElementById("imoForce").addEventListener("click",function(){w(!0)}),k.getElementById("imoOpen").addEventListener("click",function(){const e=k.getElementById("imoInput").value.trim();E(e,!0)?s(o(e)):alert("Please enter a valid IMO number first")}),k.getElementById("imoCopy").addEventListener("click",function(){const e=k.getElementById("imoInput").value.trim();if(!E(e,!0))return void alert("Please enter a valid IMO number first");const t=Object.values(o(e)).join("\n");l(t).then(function(){alert("Links copied to clipboard!")}).catch(function(){prompt("Copy these links:",t)})}),k.getElementById("imoCSV").addEventListener("click",function(){const e=k.getElementById("imoInput").value.trim();if(!E(e,!0))return void alert("Please enter a valid IMO number first");m("vessel_imo_"+e+"_links.csv",c(d("IMO",e,o(e))))}),k.getElementById("mmsiOpen").addEventListener("click",function(){const e=k.getElementById("mmsiInput").value.trim();i(e)?s(a(e)):alert("Please enter a valid MMSI number first")}),k.getElementById("mmsiCopy").addEventListener("click",function(){const e=k.getElementById("mmsiInput").value.trim();if(!i(e))return void alert("Please enter a valid MMSI number first");const t=Object.values(a(e)).join("\n");l(t).then(function(){alert("Links copied to clipboard!")}).catch(function(){prompt("Copy these links:",t)})}),k.getElementById("mmsiCSV").addEventListener("click",function(){const e=k.getElementById("mmsiInput").value.trim();if(!i(e))return void alert("Please enter a valid MMSI number first");m("vessel_mmsi_"+e+"_links.csv",c(d("MMSI",e,a(e))))}),k.getElementById("nameOpen").addEventListener("click",function(){const e=k.getElementById("nameInput").value.trim();e.length<3?alert("Please enter a vessel name with at least 3 characters"):s(r(e))}),k.getElementById("nameCopy").addEventListener("click",function(){const e=k.getElementById("nameInput").value.trim();if(e.length<3)return void alert("Please enter a vessel name with at least 3 characters");const t=Object.values(r(e)).join("\n");l(t).then(function(){alert("Links copied to clipboard!")}).catch(function(){prompt("Copy these links:",t)})}),k.getElementById("nameCSV").addEventListener("click",function(){const e=k.getElementById("nameInput").value.trim();if(e.length<3)return void alert("Please enter a vessel name with at least 3 characters");const t=c(d("NAME",e,r(e)));m("vessel_name_"+e.replace(/[^a-zA-Z0-9]/g,"_")+"_links.csv",t)}),u.addEventListener("beforeunload",function(){delete window.vesselTrackerRunning}),k.getElementById("imoInput").focus(),alert("Vessel Tracker loaded successfully!")}catch(C){console.error("Vessel Tracker Error:",C),alert("An error occurred: "+C.message)}finally{window.vesselTrackerPopupOpen||setTimeout(function(){delete window.vesselTrackerRunning},1e3)}}}();">
Vessel Track
</a>
<button class="copy-btn" onclick="copyBookmarkletCode(this)">Copy Code</button>
</div>
</div>
<div class="bookmarklet-description">
Generate tracking links for vessels across multiple maritime platforms using IMO, MMSI, or vessel name with validation and export.
</div>
<ul class="features">
<li>Multiple search methods: IMO number, MMSI number, or vessel name</li>
<li>Links to MarineTraffic, VesselFinder, FleetMon, and more</li>
<li>Built-in IMO/MMSI validation</li>
<li>Batch link opening across platforms</li>
<li>Export tracking links as text</li>
</ul>
</div>
<div class="bookmarklet">
<div class="bookmarklet-header">
<div class="bookmarklet-title">🕵️ Website Recon Scanner</div>
<div class="button-group">
<a href="javascript:void(0)"
class="bookmarklet-link"
draggable="true"
data-bookmarklet-name="Website Recon Scanner"
title="Drag this button to your bookmarks bar"
data-bookmarklet-code="javascript:!function(){"use strict";const e="2.0.0",t="Website Recon Scanner",n="websiteReconScannerV2",a=150,i=8e3,r=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)||window.innerWidth<=768;if(window.websiteReconScanner)try{return void window.websiteReconScanner.focus()}catch(v){try{window.websiteReconScanner.close()}catch(S){}}try{let E="",k="";try{window.location&&window.location.href&&(E=window.location.href,k=window.location.origin)}catch(ie){E="",k=""}const C=document,F=document.cookie;let A={discoveryFiles:[],developmentFiles:[],wellKnown:[],apiEndpoints:[],securityFiles:[],metaInfo:[],technologies:[],securityHeaders:[],cookies:[],socialMedia:[],externalResources:[],contacts:[],summary:{}};const R=[{path:"/robots.txt",name:"robots.txt",description:"Search engine crawl instructions"},{path:"/sitemap.xml",name:"sitemap.xml",description:"XML sitemap for search engines"},{path:"/sitemap_index.xml",name:"sitemap_index.xml",description:"Sitemap index file"},{path:"/security.txt",name:"security.txt",description:"Security contact info (RFC 9116)"},{path:"/humans.txt",name:"humans.txt",description:"Team and technology credits"},{path:"/manifest.json",name:"manifest.json",description:"Web app manifest (PWA)"},{path:"/manifest.webmanifest",name:"manifest.webmanifest",description:"Web app manifest alt"},{path:"/browserconfig.xml",name:"browserconfig.xml",description:"IE/Edge tile configuration"},{path:"/crossdomain.xml",name:"crossdomain.xml",description:"Flash cross-domain policy"},{path:"/ads.txt",name:"ads.txt",description:"Authorized digital sellers"},{path:"/app-ads.txt",name:"app-ads.txt",description:"App authorized digital sellers"},{path:"/favicon.ico",name:"favicon.ico",description:"Site favicon"},{path:"/apple-touch-icon.png",name:"apple-touch-icon.png",description:"iOS home screen icon"},{path:"/feed/",name:"feed/",description:"RSS/Atom feed"},{path:"/rss",name:"rss",description:"RSS feed alternate"},{path:"/atom.xml",name:"atom.xml",description:"Atom feed"}],I=[{path:"/README.md",name:"README.md",description:"Project documentation"},{path:"/LICENSE",name:"LICENSE",description:"License information"},{path:"/LICENSE.txt",name:"LICENSE.txt",description:"License information (txt)"},{path:"/package.json",name:"package.json",description:"Node.js package info"},{path:"/composer.json",name:"composer.json",description:"PHP Composer config"},{path:"/Gemfile",name:"Gemfile",description:"Ruby dependencies"},{path:"/requirements.txt",name:"requirements.txt",description:"Python dependencies"},{path:"/.env",name:".env",description:"Environment variables (sensitive!)"},{path:"/.env.example",name:".env.example",description:"Example environment file"},{path:"/docker-compose.yml",name:"docker-compose.yml",description:"Docker Compose config"},{path:"/Dockerfile",name:"Dockerfile",description:"Docker build file"},{path:"/Makefile",name:"Makefile",description:"Build automation"},{path:"/CHANGELOG.md",name:"CHANGELOG.md",description:"Version history"},{path:"/.gitignore",name:".gitignore",description:"Git ignore rules"}],P=[{path:"/.git/HEAD",name:".git/HEAD",description:"Git repository exposed (critical!)"},{path:"/.git/config",name:".git/config",description:"Git config exposed (critical!)"},{path:"/.svn/entries",name:".svn/entries",description:"SVN repository exposed"},{path:"/.DS_Store",name:".DS_Store",description:"macOS directory metadata"},{path:"/server-status",name:"server-status",description:"Apache server status"},{path:"/server-info",name:"server-info",description:"Apache server info"},{path:"/phpinfo.php",name:"phpinfo.php",description:"PHP info page (sensitive!)"},{path:"/info.php",name:"info.php",description:"PHP info alternate"},{path:"/elmah.axd",name:"elmah.axd",description:"ASP.NET error log"},{path:"/trace.axd",name:"trace.axd",description:"ASP.NET trace info"},{path:"/wp-config.php.bak",name:"wp-config.php.bak",description:"WordPress config backup"},{path:"/web.config",name:"web.config",description:"IIS configuration"},{path:"/.htaccess",name:".htaccess",description:"Apache configuration"},{path:"/.htpasswd",name:".htpasswd",description:"Apache password file (critical!)"},{path:"/backup.sql",name:"backup.sql",description:"Database backup (critical!)"},{path:"/dump.sql",name:"dump.sql",description:"Database dump (critical!)"},{path:"/debug.log",name:"debug.log",description:"Debug log file"},{path:"/error.log",name:"error.log",description:"Error log file"}],N=[{path:"/.well-known/security.txt",name:"security.txt",description:"Security contact (RFC 9116)"},{path:"/.well-known/openid-configuration",name:"openid-configuration",description:"OpenID Connect discovery"},{path:"/.well-known/apple-app-site-association",name:"apple-app-site-association",description:"iOS universal links"},{path:"/.well-known/assetlinks.json",name:"assetlinks.json",description:"Android app links"},{path:"/.well-known/change-password",name:"change-password",description:"Password change URL"},{path:"/.well-known/mta-sts.txt",name:"mta-sts.txt",description:"Mail Transfer Agent STS policy"},{path:"/.well-known/dnt-policy.txt",name:"dnt-policy.txt",description:"Do Not Track policy"},{path:"/.well-known/nodeinfo",name:"nodeinfo",description:"Fediverse node info"},{path:"/.well-known/webfinger",name:"webfinger",description:"WebFinger discovery"},{path:"/.well-known/matrix/server",name:"matrix/server",description:"Matrix server delegation"},{path:"/.well-known/jwks.json",name:"jwks.json",description:"JSON Web Key Set"}],T=[{path:"/api",name:"API Root",description:"Main API endpoint"},{path:"/api/v1",name:"API v1",description:"API version 1"},{path:"/api/v2",name:"API v2",description:"API version 2"},{path:"/graphql",name:"GraphQL",description:"GraphQL endpoint"},{path:"/swagger",name:"Swagger UI",description:"Swagger API docs"},{path:"/swagger.json",name:"swagger.json",description:"Swagger specification"},{path:"/api-docs",name:"API Docs",description:"API documentation"},{path:"/openapi.json",name:"openapi.json",description:"OpenAPI specification"},{path:"/rest",name:"REST",description:"REST API root"},{path:"/wp-json",name:"WP REST API",description:"WordPress REST API"},{path:"/wp-json/wp/v2/users",name:"WP Users API",description:"WordPress user enumeration"},{path:"/admin",name:"Admin Panel",description:"Administration interface"},{path:"/administrator",name:"Administrator",description:"Joomla admin panel"},{path:"/wp-admin",name:"WP Admin",description:"WordPress admin panel"},{path:"/wp-login.php",name:"WP Login",description:"WordPress login page"},{path:"/login",name:"Login",description:"Login page"},{path:"/health",name:"Health Check",description:"Health endpoint"},{path:"/status",name:"Status",description:"Status endpoint"},{path:"/metrics",name:"Metrics",description:"Prometheus metrics"},{path:"/debug",name:"Debug",description:"Debug endpoint"},{path:"/xmlrpc.php",name:"XML-RPC",description:"WordPress XML-RPC (attack surface)"}],M=[{name:"jQuery",pattern:/jquery[.\-\/]?(\d[\d.]*)?/i,type:"Library"},{name:"React",pattern:/react[.\-\/]|__react/i,type:"Framework"},{name:"Angular",pattern:/angular[.\-\/]|ng-version/i,type:"Framework"},{name:"Vue.js",pattern:/vue[.\-\/]|__vue/i,type:"Framework"},{name:"Svelte",pattern:/svelte[.\-\/]/i,type:"Framework"},{name:"Next.js",pattern:/next[.\-\/]|__next|_next/i,type:"Framework"},{name:"Nuxt.js",pattern:/nuxt[.\-\/]|__nuxt/i,type:"Framework"},{name:"Gatsby",pattern:/gatsby/i,type:"Framework"},{name:"Ember.js",pattern:/ember[.\-\/]/i,type:"Framework"},{name:"Backbone.js",pattern:/backbone[.\-\/]/i,type:"Framework"},{name:"htmx",pattern:/htmx[.\-\/]/i,type:"Library"},{name:"Alpine.js",pattern:/alpine[.\-\/]|x-data/i,type:"Library"},{name:"Bootstrap",pattern:/bootstrap[.\-\/]/i,type:"CSS"},{name:"Tailwind CSS",pattern:/tailwind/i,type:"CSS"},{name:"Bulma",pattern:/bulma[.\-\/]/i,type:"CSS"},{name:"Foundation",pattern:/foundation[.\-\/]/i,type:"CSS"},{name:"WordPress",pattern:/wp-content|wp-includes|wordpress/i,type:"CMS"},{name:"Drupal",pattern:/drupal|sites\/default\/files/i,type:"CMS"},{name:"Joomla",pattern:/joomla|\/media\/system/i,type:"CMS"},{name:"Shopify",pattern:/shopify|cdn\.shopify\.com/i,type:"CMS"},{name:"Squarespace",pattern:/squarespace/i,type:"CMS"},{name:"Wix",pattern:/wix\.com|wixstatic/i,type:"CMS"},{name:"Webflow",pattern:/webflow/i,type:"CMS"},{name:"Ghost",pattern:/ghost[.\-\/]/i,type:"CMS"},{name:"Lodash",pattern:/lodash[.\-\/]/i,type:"Library"},{name:"Moment.js",pattern:/moment[.\-\/](\d|min)/i,type:"Library"},{name:"Axios",pattern:/axios[.\-\/]/i,type:"Library"},{name:"D3.js",pattern:/d3[.\-\/](\d|min)/i,type:"Library"},{name:"Three.js",pattern:/three[.\-\/]/i,type:"Library"},{name:"Socket.IO",pattern:/socket\.io/i,type:"Library"},{name:"GSAP",pattern:/gsap|greensock/i,type:"Library"},{name:"Google Analytics",pattern:/google-analytics|googletagmanager|gtag|ga\.js|analytics\.js/i,type:"Analytics"},{name:"Google Tag Manager",pattern:/googletagmanager\.com\/gtm/i,type:"Analytics"},{name:"Facebook Pixel",pattern:/connect\.facebook\.net|fbevents/i,type:"Analytics"},{name:"Hotjar",pattern:/hotjar/i,type:"Analytics"},{name:"Mixpanel",pattern:/mixpanel/i,type:"Analytics"},{name:"Segment",pattern:/segment\.com|analytics\.min\.js/i,type:"Analytics"},{name:"Plausible",pattern:/plausible/i,type:"Analytics"},{name:"Matomo",pattern:/matomo|piwik/i,type:"Analytics"},{name:"Cloudflare",pattern:/cloudflare|cf-ray/i,type:"Infrastructure"},{name:"AWS CloudFront",pattern:/cloudfront\.net/i,type:"Infrastructure"},{name:"Fastly",pattern:/fastly/i,type:"Infrastructure"},{name:"Akamai",pattern:/akamai/i,type:"Infrastructure"},{name:"Vercel",pattern:/vercel|\.vercel\.app/i,type:"Infrastructure"},{name:"Netlify",pattern:/netlify/i,type:"Infrastructure"},{name:"PHP",pattern:/\.php|x-powered-by.*php/i,type:"Server"},{name:"ASP.NET",pattern:/asp\.net|__viewstate|aspnet/i,type:"Server"},{name:"Ruby on Rails",pattern:/ruby|rails/i,type:"Server"},{name:"Django",pattern:/csrfmiddlewaretoken|django/i,type:"Server"},{name:"Laravel",pattern:/laravel/i,type:"Server"},{name:"Express",pattern:/express/i,type:"Server"}],L=[{name:"Facebook",pattern:/facebook\.com|fb\.com/i},{name:"Twitter/X",pattern:/twitter\.com|x\.com/i},{name:"LinkedIn",pattern:/linkedin\.com/i},{name:"Instagram",pattern:/instagram\.com/i},{name:"YouTube",pattern:/youtube\.com|youtu\.be/i},{name:"TikTok",pattern:/tiktok\.com/i},{name:"GitHub",pattern:/github\.com/i},{name:"Reddit",pattern:/reddit\.com/i},{name:"Pinterest",pattern:/pinterest\.com/i},{name:"Discord",pattern:/discord\.gg|discord\.com/i},{name:"Telegram",pattern:/t\.me|telegram\.org/i},{name:"Mastodon",pattern:/mastodon|joinmastodon/i},{name:"Bluesky",pattern:/bsky\.app|bsky\.social/i},{name:"Medium",pattern:/medium\.com/i},{name:"Threads",pattern:/threads\.net/i}],j=[{name:"Content-Security-Policy",critical:!0,description:"Controls resource loading"},{name:"Strict-Transport-Security",critical:!0,description:"Enforces HTTPS (HSTS)"},{name:"X-Frame-Options",critical:!0,description:"Clickjacking protection"},{name:"X-Content-Type-Options",critical:!1,description:"MIME sniffing prevention"},{name:"X-XSS-Protection",critical:!1,description:"XSS filter (legacy)"},{name:"Referrer-Policy",critical:!1,description:"Controls referrer info"},{name:"Permissions-Policy",critical:!1,description:"Feature permissions"},{name:"Cross-Origin-Opener-Policy",critical:!1,description:"Cross-origin isolation"},{name:"Cross-Origin-Embedder-Policy",critical:!1,description:"Cross-origin embedding"},{name:"Cross-Origin-Resource-Policy",critical:!1,description:"Cross-origin resource sharing"},{name:"X-Permitted-Cross-Domain-Policies",critical:!1,description:"Flash/PDF cross-domain"}],O=r?"width=420,height=750,scrollbars=yes,resizable=yes":"width=900,height=950,scrollbars=yes,resizable=yes";if(window.websiteReconScanner=window.open("",n,O),!window.websiteReconScanner)return void alert("Popup blocked! Please allow popups for this site.");const D=window.websiteReconScanner.document;D.open(),D.write('<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Website Recon Scanner</title></head><body></body></html>'),D.close();const H=D.createElement("style");H.textContent=["* { box-sizing: border-box; margin: 0; padding: 0; }",'body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #0f172a; color: #e2e8f0; padding: 20px; line-height: 1.5; }',".container { max-width: 860px; margin: 0 auto; }",".header { text-align: center; padding: 24px 0; border-bottom: 1px solid #1e293b; margin-bottom: 24px; }",".header h1 { font-size: 22px; font-weight: 700; color: #f1f5f9; margin-bottom: 4px; }",".header .target { font-size: 14px; color: #94a3b8; word-break: break-all; }",".header .target a { color: #60a5fa; text-decoration: none; }",".summary-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 12px; margin-bottom: 24px; }",".summary-card { background: #1e293b; border: 1px solid #334155; border-radius: 10px; padding: 16px; text-align: center; transition: border-color 0.2s; }",".summary-card.critical { border-color: #ef4444; }",".summary-card.warning { border-color: #f59e0b; }",".summary-card.good { border-color: #22c55e; }",".summary-number { font-size: 28px; font-weight: 700; color: #f1f5f9; }",".summary-label { font-size: 11px; color: #94a3b8; text-transform: uppercase; letter-spacing: 0.5px; margin-top: 4px; }",".controls { display: flex; gap: 10px; margin-bottom: 24px; flex-wrap: wrap; }",".btn { padding: 10px 20px; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s; color: white; }",".btn:hover { transform: translateY(-1px); }",".btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }",".btn-scan { background: #3b82f6; flex: 1; min-width: 140px; }",".btn-scan:hover { background: #2563eb; }",".btn-export { background: #1e293b; border: 1px solid #334155; color: #cbd5e1; }",".btn-export:hover { background: #334155; }",".btn-stop { background: #ef4444; }",".btn-stop:hover { background: #dc2626; }",".progress-section { background: #1e293b; border: 1px solid #334155; border-radius: 10px; padding: 16px; margin-bottom: 24px; display: none; }",".progress-text { font-size: 13px; color: #94a3b8; margin-bottom: 8px; }",".progress-bar-bg { background: #334155; border-radius: 4px; height: 6px; overflow: hidden; }",".progress-bar-fill { background: linear-gradient(90deg, #3b82f6, #8b5cf6); height: 100%; width: 0%; border-radius: 4px; transition: width 0.3s; }",".category-section { margin-bottom: 16px; background: #1e293b; border: 1px solid #334155; border-radius: 10px; overflow: hidden; }",".category-header { display: flex; justify-content: space-between; align-items: center; padding: 14px 16px; cursor: pointer; user-select: none; transition: background 0.2s; }",".category-header:hover { background: #334155; }",".category-left { display: flex; align-items: center; gap: 10px; }",".category-icon { font-size: 16px; }",".category-name { font-weight: 600; font-size: 14px; color: #f1f5f9; }",".category-badge { font-size: 11px; padding: 2px 8px; border-radius: 10px; font-weight: 600; }",".badge-found { background: #166534; color: #86efac; }",".badge-none { background: #334155; color: #94a3b8; }",".badge-critical { background: #991b1b; color: #fca5a5; }",".category-arrow { color: #64748b; transition: transform 0.2s; font-size: 12px; }",".category-arrow.open { transform: rotate(90deg); }",".category-content { display: none; border-top: 1px solid #334155; }",".category-content.expanded { display: block; }",".finding-item { display: flex; align-items: center; padding: 10px 16px; border-bottom: 1px solid #1e293b; font-size: 13px; gap: 10px; }",".finding-item:last-child { border-bottom: none; }",".finding-item:hover { background: rgba(51, 65, 85, 0.3); }",".status-badge { font-size: 10px; padding: 2px 8px; border-radius: 4px; font-weight: 700; text-transform: uppercase; white-space: nowrap; letter-spacing: 0.3px; }",".status-found { background: #166534; color: #86efac; }",".status-missing { background: #334155; color: #64748b; }",".status-critical { background: #991b1b; color: #fca5a5; }",".status-warning { background: #92400e; color: #fcd34d; }",".status-good { background: #166534; color: #86efac; }",".finding-name { font-weight: 500; color: #e2e8f0; min-width: 160px; }",".finding-desc { color: #94a3b8; flex: 1; }",".finding-value { color: #cbd5e1; font-family: monospace; font-size: 12px; max-width: 350px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }",".footer { text-align: center; padding: 20px 0; border-top: 1px solid #1e293b; margin-top: 24px; color: #475569; font-size: 12px; }","@media (max-width: 600px) { body { padding: 12px; } .summary-grid { grid-template-columns: repeat(2, 1fr); } .finding-item { flex-wrap: wrap; } .finding-desc { display: none; } }"].join("\n"),D.head.appendChild(H);let q=!1;function W(e,t){return t=t||i,new Promise(function(n,a){const i=new XMLHttpRequest,r=setTimeout(function(){i.abort(),a(new Error("Timeout"))},t);i.onreadystatechange=function(){if(4===i.readyState){clearTimeout(r);const e={};try{const t=i.getAllResponseHeaders();t&&t.trim().split(/[\r\n]+/).forEach(function(t){const n=t.split(": "),a=n.shift();e[a.toLowerCase()]=n.join(": ")})}catch(e){}n({status:i.status,responseText:i.responseText,headers:e})}},i.onerror=function(){clearTimeout(r),a(new Error("Network error"))};try{i.open("GET",e,!0),i.send()}catch(e){clearTimeout(r),a(e)}})}function z(e,t){const n=D.querySelector(".progress-bar-fill"),a=D.querySelector(".progress-text");n&&(n.style.width=e+"%"),a&&(a.textContent=t)}async function G(e,t,n,i){const r=[];let o=0;for(let i=0;i<e.length&&!q;i++){const s=e[i];z(t+i/e.length*(n-t),"Checking "+s.name+"...");try{const e=await W(k+s.path),t=e.status>=200&&e.status<400;t&&o++,r.push({name:s.name,path:s.path,description:s.description,found:t,status:e.status,size:e.responseText?e.responseText.length:0,headers:e.headers||{}})}catch(e){r.push({name:s.name,path:s.path,description:s.description,found:!1,status:"Error",size:0,headers:{}})}await new Promise(function(e){setTimeout(e,a)})}return A[i]=r,A.summary[i+"Found"]=o,A.summary[i+"Total"]=e.length,r}function U(){z(85,"Analyzing security headers...");const e=[],t={};return[].concat(A.discoveryFiles||[],A.wellKnown||[]).forEach(function(e){e.headers&&Object.keys(e.headers).forEach(function(n){t[n]||(t[n]=e.headers[n])})}),j.forEach(function(n){const a=n.name.toLowerCase(),i=t[a]||null;e.push({name:n.name,description:n.description,found:!!i,value:i||"Not set",critical:n.critical})}),t.server&&e.push({name:"Server",description:"Server software disclosure",found:!0,value:t.server,critical:!1}),t["x-powered-by"]&&e.push({name:"X-Powered-By",description:"Technology disclosure",found:!0,value:t["x-powered-by"],critical:!1}),A.securityHeaders=e,A.summary.securityHeadersSet=e.filter(function(e){return e.found}).length,A.summary.securityHeadersMissing=e.filter(function(e){return!e.found}).length,A.summary.securityHeadersCritical=e.filter(function(e){return e.critical&&!e.found}).length,e}function B(){z(88,"Extracting meta information...");const e=[];e.push({name:"Page Title",value:C.title||"Not found",found:!!C.title}),C.querySelectorAll("meta").forEach(function(t){const n=t.getAttribute("name")||t.getAttribute("property")||t.getAttribute("http-equiv"),a=t.getAttribute("content");n&&a&&e.push({name:n,value:a,found:!0})});var t=C.querySelector('link[rel="canonical"]');t&&e.push({name:"Canonical URL",value:t.href,found:!0});var n=C.documentElement.lang;n&&e.push({name:"Language",value:n,found:!0});var a=C.querySelector('link[rel="icon"], link[rel="shortcut icon"]');return a&&e.push({name:"Favicon",value:a.href,found:!0}),A.metaInfo=e,A.summary.metaInfoFound=e.filter(function(e){return e.found}).length,e}function _(){z(90,"Detecting technologies...");const e=[],t={};C.querySelectorAll("script[src]").forEach(function(n){var a=n.src||"";M.forEach(function(n){n.pattern.test(a)&&!t[n.name]&&(t[n.name]=!0,e.push({name:n.name,type:n.type,found:!0,source:a}))})}),C.querySelectorAll("script:not([src])").forEach(function(n){var a=n.textContent||"";M.forEach(function(n){n.pattern.test(a)&&!t[n.name]&&(t[n.name]=!0,e.push({name:n.name,type:n.type,found:!0,source:"inline script"}))})}),C.querySelectorAll("link[href]").forEach(function(n){var a=n.href||"";M.forEach(function(n){n.pattern.test(a)&&!t[n.name]&&(t[n.name]=!0,e.push({name:n.name,type:n.type,found:!0,source:a}))})});var n=C.querySelector('meta[name="generator"]');if(n){var a=n.getAttribute("content")||"";e.push({name:a,type:"Generator",found:!0,source:"meta generator"})}var i=C.documentElement.outerHTML.substring(0,5e3);return M.forEach(function(n){n.pattern.test(i)&&!t[n.name]&&(t[n.name]=!0,e.push({name:n.name,type:n.type,found:!0,source:"HTML content"}))}),A.technologies=e,A.summary.technologiesFound=e.length,e}function K(){z(92,"Analyzing cookies...");const e=[];return F&&F.split(";").forEach(function(t){var n=t.trim().split("="),a=n[0],i=n.slice(1).join("=");a&&e.push({name:a.trim(),value:i?i.length>60?i.substring(0,60)+"...":i:"(empty)",found:!0})}),A.cookies=e,A.summary.cookiesFound=e.length,e}function X(){z(94,"Finding social media links...");const e=[],t={};return C.querySelectorAll("a[href]").forEach(function(n){var a=n.href||"";L.forEach(function(n){n.pattern.test(a)&&!t[n.name+":"+a]&&(t[n.name+":"+a]=!0,e.push({name:n.name,value:a,found:!0}))})}),A.socialMedia=e,A.summary.socialMediaFound=Object.keys(e.reduce(function(e,t){return e[t.name]=!0,e},{})).length,e}function V(){z(95,"Finding contact information...");const e=[];var t=C.body&&C.body.textContent||"",n=[],a=t.match(/\b[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}\b/g);return a&&a.forEach(function(e){-1===n.indexOf(e)&&n.push(e)}),C.querySelectorAll('a[href^="mailto:"]').forEach(function(e){var t=e.href.replace("mailto:","").split("?")[0];-1===n.indexOf(t)&&n.push(t)}),n.slice(0,15).forEach(function(t){e.push({name:"Email",value:t,found:!0})}),C.querySelectorAll('a[href^="tel:"]').forEach(function(t){e.push({name:"Phone",value:t.href.replace("tel:",""),found:!0})}),A.contacts=e,A.summary.contactsFound=e.length,e}function Y(){z(97,"Analyzing external resources...");const e=[],t={};var n="";try{n=new URL(E).hostname}catch(e){}function a(a,i){try{var r=new URL(a);r.hostname&&r.hostname!==n&&!t[r.hostname]&&(t[r.hostname]=!0,e.push({name:r.hostname,value:a,type:i,found:!0}))}catch(e){}}return C.querySelectorAll("script[src]").forEach(function(e){a(e.src,"Script")}),C.querySelectorAll("link[href]").forEach(function(e){a(e.href,"Stylesheet")}),C.querySelectorAll("img[src]").forEach(function(e){a(e.src,"Image")}),C.querySelectorAll("iframe[src]").forEach(function(e){a(e.src,"iFrame")}),A.externalResources=e,A.summary.externalResourcesFound=e.length,e}function J(e){return String(e||"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function Q(){var e=D.getElementById("resultsArea");if(e){for(;e.firstChild;)e.removeChild(e.firstChild);[{id:"securityFiles",name:"Sensitive Files & Exposure",icon:"🚨",data:A.securityFiles||[],isCritical:!0},{id:"securityHeaders",name:"Security Headers",icon:"🛡",data:A.securityHeaders||[],isHeaders:!0},{id:"discoveryFiles",name:"Discovery Files",icon:"📄",data:A.discoveryFiles||[]},{id:"wellKnown",name:"Well-Known URIs",icon:"🔗",data:A.wellKnown||[]},{id:"apiEndpoints",name:"API Endpoints & Admin Panels",icon:"🔌",data:A.apiEndpoints||[]},{id:"developmentFiles",name:"Development Files",icon:"🔧",data:A.developmentFiles||[]},{id:"technologies",name:"Technologies Detected",icon:"⚙",data:A.technologies||[],isTech:!0},{id:"metaInfo",name:"Meta Information",icon:"📋",data:A.metaInfo||[],isMeta:!0},{id:"cookies",name:"Cookies",icon:"🍪",data:A.cookies||[],isMeta:!0},{id:"socialMedia",name:"Social Media Links",icon:"🌐",data:A.socialMedia||[],isMeta:!0},{id:"contacts",name:"Contact Information",icon:"📧",data:A.contacts||[],isMeta:!0},{id:"externalResources",name:"External Resources",icon:"🔗",data:A.externalResources||[],isExternal:!0}].forEach(function(t){if(0!==t.data.length){var n=D.createElement("div");n.className="category-section";var a=t.data.filter(function(e){return e.found}).length,i="badge-none",r="0 found";if(t.isCritical&&a>0)i="badge-critical",r=a+" EXPOSED";else if(t.isHeaders){i="badge-found",r=t.data.filter(function(e){return e.found}).length+"/"+t.data.length+" set"}else a>0&&(i="badge-found",r=a+" found");var o=D.createElement("div");o.className="category-header";var s=D.createElement("div");s.className="category-left";var c=D.createElement("span");c.className="category-icon",c.textContent=t.icon;var l=D.createElement("span");l.className="category-name",l.textContent=t.name;var d=D.createElement("span");d.className="category-badge "+i,d.textContent=r,s.appendChild(c),s.appendChild(l),s.appendChild(d);var p=D.createElement("span");p.className="category-arrow",p.textContent="▶",o.appendChild(s),o.appendChild(p),n.appendChild(o);var m=D.createElement("div");m.className="category-content",t.data.forEach(function(e){var n=D.createElement("div");n.className="finding-item";var a="status-missing",i="NOT FOUND";t.isHeaders?e.found?(a="status-good",i="SET"):e.critical?(a="status-critical",i="MISSING"):(a="status-warning",i="MISSING"):t.isCritical&&e.found?(a="status-critical",i="EXPOSED"):e.found&&(a="status-found",i="FOUND"),(t.isMeta||t.isExternal||t.isTech)&&(a="status-found",i=e.type||"FOUND");var r=D.createElement("span");r.className="status-badge "+a,r.textContent=i;var o=D.createElement("span");o.className="finding-name",o.textContent=e.name||"";var s=D.createElement("span");if(s.className="finding-desc",s.textContent=e.description||"",n.appendChild(r),n.appendChild(o),n.appendChild(s),e.value){var c=D.createElement("span");c.className="finding-value",c.title=String(e.value),c.textContent=String(e.value).substring(0,80),n.appendChild(c)}m.appendChild(n)}),n.appendChild(m),e.appendChild(n),o.addEventListener("click",function(){m.classList.toggle("expanded"),p.classList.toggle("open")})}}),Z()}}function Z(){var e=A.summary,t=(e.discoveryFilesFound||0)+(e.developmentFilesFound||0)+(e.wellKnownFound||0)+(e.apiEndpointsFound||0),n=e.securityFilesFound||0,a=e.securityHeadersMissing||0,i=e.technologiesFound||0,r=e.contactsFound||0,o=e.externalResourcesFound||0,s=D.querySelectorAll(".summary-card");s.length>=6&&(s[0].querySelector(".summary-number").textContent=t,s[0].className="summary-card"+(t>5?" good":""),s[1].querySelector(".summary-number").textContent=n,s[1].className="summary-card"+(n>0?" critical":" good"),s[2].querySelector(".summary-number").textContent=a,s[2].className="summary-card"+(a>3?" critical":a>0?" warning":" good"),s[3].querySelector(".summary-number").textContent=i,s[4].querySelector(".summary-number").textContent=r,s[5].querySelector(".summary-number").textContent=o)}function $(){try{return new URL(E).hostname.replace(/\./g,"-")}catch(e){return"unknown"}}function ee(){return(new Date).toISOString().split("T")[0]}function te(e,t,n){var a=new Blob([e],{type:n}),i=URL.createObjectURL(a),r=D.createElement("a");r.href=i,r.download=t,D.body.appendChild(r),r.click(),D.body.removeChild(r),URL.revokeObjectURL(i)}function ne(){var t=A.summary,n=[];function a(e,t,n){if(!t||0===t.length)return"";var a=n?t:t.filter(function(e){return e.found});if(0===a.length)return"";var i="<h2>"+J(e)+"</h2><table><tr><th>Status</th><th>Name</th><th>Details</th></tr>";return a.forEach(function(t){var n=t.found?"found":t.critical?"critical":"missing",a=t.found?"Found":"Missing",r=e.indexOf("Sensitive")>=0&&t.found;i+='<tr class="'+(r?"critical":"")+'"><td class="'+n+'">'+a+"</td><td>"+J(t.name)+"</td><td>"+J(t.value||t.description||"")+"</td></tr>"}),i+"</table>"}n.push('<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Recon Report - '+J(E)+"</title>"),n.push("<style>body{font-family:sans-serif;max-width:900px;margin:40px auto;padding:20px;color:#1e293b;line-height:1.6}h1{border-bottom:2px solid #3b82f6;padding-bottom:8px}h2{color:#334155;margin-top:30px;border-bottom:1px solid #e2e8f0;padding-bottom:4px}table{width:100%;border-collapse:collapse;margin:12px 0}th,td{text-align:left;padding:8px 12px;border:1px solid #e2e8f0}th{background:#f1f5f9;font-weight:600}.found{color:#16a34a}.missing{color:#dc2626}.critical{background:#fef2f2;color:#991b1b;font-weight:700}.summary-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin:16px 0}.summary-card{background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:16px;text-align:center}.summary-number{font-size:28px;font-weight:700}.meta{color:#64748b;font-size:14px;margin:4px 0}</style></head><body>"),n.push("<h1>Website Reconnaissance Report</h1>"),n.push('<p class="meta">Target: <strong>'+J(E)+"</strong></p>"),n.push('<p class="meta">Date: '+J((new Date).toLocaleString())+"</p>"),n.push('<p class="meta">Scanner: Website Recon Scanner v'+e+"</p>"),n.push('<div class="summary-grid">'),n.push('<div class="summary-card"><div class="summary-number">'+((t.discoveryFilesFound||0)+(t.developmentFilesFound||0)+(t.wellKnownFound||0)+(t.apiEndpointsFound||0))+"</div><div>Files Found</div></div>"),n.push('<div class="summary-card"><div class="summary-number" style="color:#dc2626">'+(t.securityFilesFound||0)+"</div><div>Sensitive Exposed</div></div>"),n.push('<div class="summary-card"><div class="summary-number">'+(t.technologiesFound||0)+"</div><div>Technologies</div></div>"),n.push("</div>"),n.push(a("Sensitive Files",A.securityFiles,!0)),n.push(a("Security Headers",A.securityHeaders,!0)),n.push(a("Discovery Files",A.discoveryFiles,!1)),n.push(a("Technologies",A.technologies,!1)),n.push(a("Meta Information",A.metaInfo,!1)),n.push(a("Contacts",A.contacts,!1)),n.push(a("Social Media",A.socialMedia,!1)),n.push(a("External Resources",A.externalResources,!1)),n.push('<hr><p class="meta" style="text-align:center">Generated by Website Recon Scanner v'+e+"</p></body></html>"),te(n.join(""),"website-recon-"+$()+"-"+ee()+".html","text/html")}async function ae(){q=!1;var e=D.getElementById("startScanBtn"),t=D.getElementById("stopScanBtn"),n=D.querySelector(".progress-section");e&&(e.disabled=!0),t&&(t.style.display="inline-block"),n&&(n.style.display="block"),A={discoveryFiles:[],developmentFiles:[],wellKnown:[],apiEndpoints:[],securityFiles:[],metaInfo:[],technologies:[],securityHeaders:[],cookies:[],socialMedia:[],externalResources:[],contacts:[],summary:{}};try{z(0,"Starting reconnaissance..."),await G(P,0,20,"securityFiles"),q||await G(R,20,40,"discoveryFiles"),q||await G(N,40,55,"wellKnown"),q||await G(T,55,72,"apiEndpoints"),q||await G(I,72,84,"developmentFiles"),q||U(),q||B(),q||_(),q||K(),q||X(),q||V(),q||Y(),z(100,q?"Scan stopped.":"Scan complete!"),Q(),D.querySelectorAll(".btn-export").forEach(function(e){e.disabled=!1})}catch(e){z(100,"Scan error: "+e.message)}finally{e&&(e.disabled=!1),t&&(t.style.display="none")}}var o=D.createElement("div");o.className="container";var s=D.createElement("div");s.className="header";var c=D.createElement("h1");c.textContent="Website Recon Scanner v"+e;var l=D.createElement("div");l.className="target",l.textContent="Target: ";var d=D.createElement("a");d.href=E,d.target="_blank",d.textContent=E,l.appendChild(d),s.appendChild(c),s.appendChild(l),o.appendChild(s);var p=D.createElement("div");p.className="summary-grid";["Files Found","Sensitive Exposed","Headers Missing","Technologies","Contacts","External Resources"].forEach(function(e){var t=D.createElement("div");t.className="summary-card";var n=D.createElement("div");n.className="summary-number",n.textContent="-";var a=D.createElement("div");a.className="summary-label",a.textContent=e,t.appendChild(n),t.appendChild(a),p.appendChild(t)}),o.appendChild(p);var m=D.createElement("div");m.className="controls";var u=D.createElement("button");u.className="btn btn-scan",u.id="startScanBtn",u.textContent="Start Scan",m.appendChild(u);var h=D.createElement("button");h.className="btn btn-stop",h.id="stopScanBtn",h.style.display="none",h.textContent="Stop",m.appendChild(h),["TXT","JSON","HTML"].forEach(function(e){var t=D.createElement("button");t.className="btn btn-export",t.setAttribute("data-format",e.toLowerCase()),t.disabled=!0,t.textContent="Export "+e,m.appendChild(t)}),o.appendChild(m);var f=D.createElement("div");f.className="progress-section";var g=D.createElement("div");g.className="progress-text",g.textContent="Ready to scan...";var y=D.createElement("div");y.className="progress-bar-bg";var b=D.createElement("div");b.className="progress-bar-fill",y.appendChild(b),f.appendChild(g),f.appendChild(y),o.appendChild(f);var x=D.createElement("div");x.id="resultsArea",o.appendChild(x);var w=D.createElement("div");w.className="footer",w.textContent="Website Recon Scanner v"+e+" | Local Processing Only | No External Calls",o.appendChild(w),D.body.appendChild(o),u.addEventListener("click",ae),h.addEventListener("click",function(){q=!0}),D.querySelectorAll(".btn-export").forEach(function(n){n.addEventListener("click",function(){var n,a,i,r=this.getAttribute("data-format");"txt"===r?(a=A.summary,i=["=".repeat(60),"WEBSITE RECONNAISSANCE REPORT","=".repeat(60),"","Target: "+E,"Date: "+(new Date).toISOString(),"Scanner: Website Recon Scanner v"+e,"","-".repeat(40),"SUMMARY","-".repeat(40),"Files discovered: "+((a.discoveryFilesFound||0)+(a.developmentFilesFound||0)+(a.wellKnownFound||0)+(a.apiEndpointsFound||0)),"Sensitive files exposed: "+(a.securityFilesFound||0),"Security headers missing: "+(a.securityHeadersMissing||0),"Technologies detected: "+(a.technologiesFound||0),"Contacts found: "+(a.contactsFound||0),"External resources: "+(a.externalResourcesFound||0),"Cookies: "+(a.cookiesFound||0),"Social media: "+(a.socialMediaFound||0)+" platforms",""],[{title:"SENSITIVE FILES (CRITICAL)",data:A.securityFiles,showAll:!0},{title:"SECURITY HEADERS",data:A.securityHeaders,showAll:!0},{title:"DISCOVERY FILES",data:A.discoveryFiles,showAll:!1},{title:"WELL-KNOWN URIS",data:A.wellKnown,showAll:!1},{title:"API ENDPOINTS",data:A.apiEndpoints,showAll:!1},{title:"DEVELOPMENT FILES",data:A.developmentFiles,showAll:!1},{title:"TECHNOLOGIES",data:A.technologies,showAll:!1},{title:"META INFORMATION",data:A.metaInfo,showAll:!1},{title:"COOKIES",data:A.cookies,showAll:!1},{title:"SOCIAL MEDIA",data:A.socialMedia,showAll:!1},{title:"CONTACTS",data:A.contacts,showAll:!1},{title:"EXTERNAL RESOURCES",data:A.externalResources,showAll:!1}].forEach(function(e){if(e.data&&0!==e.data.length){var t=e.showAll?e.data:e.data.filter(function(e){return e.found});0!==t.length&&(i.push("-".repeat(40)),i.push(e.title),i.push("-".repeat(40)),t.forEach(function(e){var t=e.found?"[FOUND]":"[MISSING]";i.push(t+" "+e.name+(e.value?" = "+e.value:"")+(e.description?" ("+e.description+")":""))}),i.push(""))}}),i.push("=".repeat(60)),i.push("End of Report"),te(i.join("\n"),"website-recon-"+$()+"-"+ee()+".txt","text/plain")):"json"===r?(n={metadata:{tool:t,version:e,target:E,timestamp:(new Date).toISOString()},summary:A.summary,results:{securityFiles:A.securityFiles.filter(function(e){return e.found}),securityHeaders:A.securityHeaders,discoveryFiles:A.discoveryFiles.filter(function(e){return e.found}),wellKnown:A.wellKnown.filter(function(e){return e.found}),apiEndpoints:A.apiEndpoints.filter(function(e){return e.found}),developmentFiles:A.developmentFiles.filter(function(e){return e.found}),technologies:A.technologies,metaInfo:A.metaInfo,cookies:A.cookies,socialMedia:A.socialMedia,contacts:A.contacts,externalResources:A.externalResources}},te(JSON.stringify(n,null,2),"website-recon-"+$()+"-"+ee()+".json","application/json")):"html"===r&&ne()})}),window.websiteReconScanner.focus()}catch(re){if(console.error("Website Recon Scanner Error:",re),alert("Error: "+re.message),window.websiteReconScanner){try{window.websiteReconScanner.close()}catch(oe){}window.websiteReconScanner=null}}}();">
Website Recon
</a>
<button class="copy-btn" onclick="copyBookmarkletCode(this)">Copy Code</button>
</div>
</div>
<div class="bookmarklet-description">
Comprehensive website reconnaissance tool that scans 80+ paths, analyzes security headers, detects technologies, and maps external resources. Exports to TXT, JSON, and HTML.
</div>
<ul class="features">
<li>Sensitive file exposure detection (.git, .env, backups, configs)</li>
<li>Security headers audit with critical/non-critical classification</li>
<li>50+ technology detection patterns (frameworks, CMS, analytics, CDNs)</li>
<li>Social media, contact, cookie, and external resource analysis</li>
<li>Professional reports in TXT, JSON, and HTML formats</li>
</ul>
</div>
</div>
</div>
</div>
<footer style="text-align: center; padding: .8em; margin-top: 60px; background: white; border-radius: 12px; box-shadow: 0 2px 10px rgba(0,0,0,0.08); border: 1px solid #e2e8f0;">
<p style="color: #64748b; font-style: italic; margin-bottom: 8px; font-size: 0.95rem;">
"Better than a thousand hollow words, is one word that brings peace."
These tools aim to bring clarity to the complex digital world - gl0bal01
</p>
</footer>
<div class="notification" id="notification"></div>
<script>
// Initialize bookmarklets from data attributes
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.bookmarklet-link').forEach(link => {
const code = link.getAttribute('data-bookmarklet-code');
if (code && code !== 'javascript:void(0)' && !code.includes('PASTE_YOUR')) {
link.href = code;
}
});
});
// Copy bookmarklet code from data attribute
function copyBookmarkletCode(button) {
const link = button.parentElement.querySelector('.bookmarklet-link');
const code = link.getAttribute('data-bookmarklet-code');
const name = link.getAttribute('data-bookmarklet-name') || 'Bookmarklet';
if (!code || code.includes('PASTE_YOUR')) {
showNotification('Bookmarklet code not available yet!', 'error');
return;
}
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(code).then(() => {
showNotification(`${name} code copied to clipboard!`);
}).catch(() => {
fallbackCopy(code, name);
});
} else {
fallbackCopy(code, name);
}
}
function fallbackCopy(text, name) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.left = '-999999px';
textArea.style.top = '-999999px';
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
document.execCommand('copy');
showNotification(`${name} code copied to clipboard!`);
} catch (err) {
showNotification('Failed to copy. Please copy the code manually.', 'error');
}
document.body.removeChild(textArea);
}
function showNotification(message, type = 'success') {
const notification = document.getElementById('notification');
notification.textContent = message;
notification.className = 'notification' + (type === 'error' ? ' error' : '');
notification.style.display = 'block';
setTimeout(() => {
notification.style.display = 'none';
}, 4000);
}
// Search functionality
document.getElementById('search').addEventListener('input', function(e) {
const searchTerm = e.target.value.toLowerCase();
const bookmarklets = document.querySelectorAll('.bookmarklet');
bookmarklets.forEach(bookmarklet => {
const title = bookmarklet.querySelector('.bookmarklet-title').textContent.toLowerCase();
const description = bookmarklet.querySelector('.bookmarklet-description').textContent.toLowerCase();
const features = Array.from(bookmarklet.querySelectorAll('.features li')).map(li => li.textContent.toLowerCase()).join(' ');
const matches = title.includes(searchTerm) || description.includes(searchTerm) || features.includes(searchTerm);
bookmarklet.style.display = matches ? 'block' : 'none';
});
});
// Add visual feedback for drag operations
document.querySelectorAll('.bookmarklet-link').forEach(link => {
link.addEventListener('dragstart', function(e) {
this.style.opacity = '0.7';
this.style.transform = 'scale(0.95)';
});
link.addEventListener('dragend', function(e) {
this.style.opacity = '1';
this.style.transform = 'scale(1)';
});
});
</script>
</body>
</html>