VismaBouwsoftAPICalls.v1_GET_Employees Method
v1_GET_Employees() as String

This API call is used to get fields of a(n) Employee(s)

HTTP method API version
GET v1

Don’t forget to put the Authorization field in the header

API Path: /Employees/
or
API Path: /Employees/{id}
or
API Path: /Employees/{id}/image
or
API Path: /Employees/{id}/note_html
or
API Path: /Employees/{id}/note_plain
or
API Path: /Employees/{id}/note_rtf

You can make this API call:
* without the key field id to get a list of Employees
* with the key field id as the path parameter (the specific id of the Employee you want to get)

Fields

The following fields are available:

Field Name Type
id Number
name String
initials String
firstname String
surname String
username String
nr Number
groups String
address String
addressline2 String
countrycode String
zipcode String
city String
state String
telephone String
fax String
gsm String
email String
company_id Number
company_name String
function String
function_localized String
date_in_service String
date_no_longer_in_service String
date_birth String
place_birth String
language String
gender String
civil_status String
civil_status_localized String
bic String
iban String
identity_card_nr String
national_identity_nr String
social_security_nr String
partner_name String
partner_profession String
partner_date_of_birth String
partner_with_disability Boolean
partner_fiscally_dependent Boolean
children_with_disability Number
children_fiscally_dependent Number
people_with_disability Number
people_fiscally_dependent Number
healthcare_fund_name String
healthcare_fund_registration_nr String
healthcare_fund_address String
healthcare_fund_addressline2 String
healthcare_fund_countrycode String
healthcare_fund_zipcode String
healthcare_fund_city String
healthcare_fund_state String
general_practitioner String
telephone_emergency String
contract_start String
contract_end String
contract_independent Boolean
contract_type String
contract_type_localized String
classification String
employment_form String
employment_form_localized String
employment_status String
employment_status_localized String
personnel_nr String
dimona_nr String
drivers_license Boolean
drivers_license_expire_date String
acknowledgement_nr_gv String
acknowledgement_nr_tv String
acknowledgement_nr_va String
acknowledgement_nr_sv String
acknowledgement_g1 Boolean
acknowledgement_g2 Boolean
acknowledgement_l Boolean
distance_commute Number
active Boolean
ts_lastupdate String

/Employees/

API Path: /Employees/

If everything succeeds the HTTP response status is 200
(200 OK)

If there is something wrong with the request, the response status and code is 400
(400 Bad Request)

If you forget to send the Authorization, the response status is 401
(401 Unauthorized)

If what you sent can’t be processed, the response status is 500
(500 Internal Server Error)

For an explanation of all possible errors, please consult our section on possible answers to API calls here

Examples:

https://ra.bouwsoft.be/api/v1/Employees

with the following parameters :

Header Parameters :
ParameterName: Clientnr, ParameterValue: 115
ParameterName: AccessToken, ParameterValue: PrDfWxfDkfzSfOjtAfzRqtrmfOmVfGrmfDbkzrUVOjUGtrtDII

Query Parameters :
ParameterName: limit, ParameterValue: 5
ParameterName: sort, ParameterValue: id

Success gives statuscode 200 And the following result

{ “Content-Range”:“0–4/195”, “Records”: [
  {
    "id": 1,
    "name": "Lutters Carlo.",
    "initials": "Lc",
    "firstname": "Carl",
    "surname": "Lutters",
    "username": "",
    "nr": 0,
    "groups": "Bestuurder",
    "address": "Molenweg 9",
    "addressline2": "",
    "countrycode": "BE",
    "zipcode": "8377",
    "city": "Meetkerke",
    "state": "West-vlaanderen",
    "telephone": "",
    "fax": "",
    "gsm": "",
    "email": "",
    "company_id": 1,
    "company_name": "Bouwsoft",
    "function": "CEO",
    "function_localized": "CEO",
    "date_in_service": "2012–01–01",
    "date_no_longer_in_service": "",
    "date_birth": "",
    "place_birth": "",
    "language": "",
    "gender": "M",
    "civil_status": "Ongehuwd",
    "civil_status_localized": "Unmarried",
    "bic": "",
    "iban": "",
    "identity_card_nr": "",
    "national_identity_nr": "",
    "social_security_nr": "",
    "partner_name": "",
    "partner_profession": "",
    "partner_date_of_birth": "",
    "partner_with_disability": false,
    "partner_fiscally_dependent": false,
    "children_with_disability": 0,
    "children_fiscally_dependent": 0,
    "people_with_disability": 0,
    "people_fiscally_dependent": 0,
    "healthcare_fund_name": "",
    "healthcare_fund_registration_nr": "",
    "healthcare_fund_address": "",
    "healthcare_fund_addressline2": "",
    "healthcare_fund_countrycode": "",
    "healthcare_fund_zipcode": "",
    "healthcare_fund_city": "",
    "healthcare_fund_state": "",
    "general_practitioner": "",
    "telephone_emergency": "",
    "contract_start": "",
    "contract_end": "",
    "contract_independent": false,
    "contract_type": "",
    "contract_type_localized": "",
    "classification": "",
    "employment_form": "",
    "employment_form_localized": "",
    "employment_status": "",
    "employment_status_localized": "",
    "personnel_nr": "",
    "dimona_nr": "",
    "drivers_license": false,
    "drivers_license_expire_date": "",
    "acknowledgement_nr_gv": "",
    "acknowledgement_nr_tv": "",
    "acknowledgement_nr_va": "",
    "acknowledgement_nr_sv": "",
    "acknowledgement_g1": false,
    "acknowledgement_g2": false,
    "acknowledgement_l": false,
    "distance_commute": 0.697912,
    "active": true,
    "ts_lastupdate": "2024–08–14 12:04:21"
  },
  {
    "id": 3,
    "name": "Deblauwe Gino",
    "initials": "Dg",
    "firstname": "Gino",
    "surname": "Deblauwe",
    "username": "SPIKKEL",
    "nr": 1002,
    "groups": "Algemene Bouwwerken, Arbeider",
    "address": "Gruuthof 24",
    "addressline2": "",
    "countrycode": "BE",
    "zipcode": "8490",
    "city": "Varsenare",
    "state": "West-vlaanderen",
    "telephone": "+32 50 45 87 58 ",
    "fax": "",
    "gsm": "+32 475 36 36 36 ",
    "email": "gino@spikesoft.be",
    "company_id": 1,
    "company_name": "Bouwsoft",
    "function": "Bediende",
    "function_localized": "White-collar worker",
    "date_in_service": "2003–01–13",
    "date_no_longer_in_service": "",
    "date_birth": "1994–08–28",
    "place_birth": "d",
    "language": "Nederlands",
    "gender": "M",
    "civil_status": "Samenwonend",
    "civil_status_localized": "Cohabiting",
    "bic": "GKCC BE BB",
    "iban": "BE59775584823226",
    "identity_card_nr": "a",
    "national_identity_nr": "79082821380",
    "social_security_nr": "b",
    "partner_name": "",
    "partner_profession": "",
    "partner_date_of_birth": "",
    "partner_with_disability": false,
    "partner_fiscally_dependent": false,
    "children_with_disability": 0,
    "children_fiscally_dependent": 2,
    "people_with_disability": 0,
    "people_fiscally_dependent": 0,
    "healthcare_fund_name": "",
    "healthcare_fund_registration_nr": "",
    "healthcare_fund_address": "",
    "healthcare_fund_addressline2": "",
    "healthcare_fund_countrycode": "",
    "healthcare_fund_zipcode": "",
    "healthcare_fund_city": "",
    "healthcare_fund_state": "",
    "general_practitioner": "Dr Bertrem",
    "telephone_emergency": "+32 (0) 50 45 45 45",
    "contract_start": "2013–01–01",
    "contract_end": "2013–12–31",
    "contract_independent": false,
    "contract_type": "Onbepaalde duur",
    "contract_type_localized": "Unlimited period",
    "classification": "fqsdf",
    "employment_form": "Voltijds",
    "employment_form_localized": "Full-time",
    "employment_status": "Arbeider",
    "employment_status_localized": "Manual labourer",
    "personnel_nr": "abc",
    "dimona_nr": "",
    "drivers_license": true,
    "drivers_license_expire_date": "2011–04–08",
    "acknowledgement_nr_gv": "",
    "acknowledgement_nr_tv": "",
    "acknowledgement_nr_va": "",
    "acknowledgement_nr_sv": "",
    "acknowledgement_g1": false,
    "acknowledgement_g2": false,
    "acknowledgement_l": false,
    "distance_commute": 9.224,
    "active": true,
    "ts_lastupdate": "2024–08–14 12:04:21"
  }
,

]
}

/Employees/{id}

If everything succeeds the HTTP response status is 200
(200 OK)

If there is something wrong with the request, the response status and code is 400
(400 Bad Request)

If there is no record that has the requested id the HTTP response status and code is 404
(404 Not found)

If you forget to send the Authorization, the response status is 401
(401 Unauthorized)

If what you sent can’t be processed, the response status is 500
(500 Internal Server Error)

For an explanation of all possible errors, please consult our section on possible answers to API calls here

Examples:

https://ra.bouwsoft.be/api/v1/Employees/532

with the following parameters :

Header Parameters :
ParameterName: Clientnr, ParameterValue: 115
ParameterName: AccessToken, ParameterValue: OPtfWxfUPbzSfDDAbfzRqtjlfVrGfGDjffPkzjtDjtOGPAPOkG

Success gives statuscode 200 And the following result

{ “Content-Range”:“0–0/1”, “Records”: [
  {
    "id": 532,
    "name": "WnDirk API",
    "initials": "",
    "firstname": "wnDirk",
    "surname": "API",
    "username": "",
    "nr": 2018233,
    "groups": "",
    "address": "matongewijk 17",
    "addressline2": "",
    "countrycode": "BE",
    "zipcode": "1000",
    "city": "Brussel 1",
    "state": "Brussels Hoofdstedelijk Gewest",
    "telephone": "",
    "fax": "",
    "gsm": "",
    "email": "",
    "company_id": 2,
    "company_name": "Groensoft",
    "function": "",
    "function_localized": "",
    "date_in_service": "",
    "date_no_longer_in_service": "",
    "date_birth": "",
    "place_birth": "",
    "language": "Nederlands",
    "gender": "M",
    "civil_status": "",
    "civil_status_localized": "",
    "bic": "",
    "iban": "",
    "identity_card_nr": "",
    "national_identity_nr": "",
    "social_security_nr": "",
    "partner_name": "",
    "partner_profession": "",
    "partner_date_of_birth": "",
    "partner_with_disability": false,
    "partner_fiscally_dependent": false,
    "children_with_disability": 0,
    "children_fiscally_dependent": 0,
    "people_with_disability": 0,
    "people_fiscally_dependent": 0,
    "healthcare_fund_name": "",
    "healthcare_fund_registration_nr": "",
    "healthcare_fund_address": "",
    "healthcare_fund_addressline2": "",
    "healthcare_fund_countrycode": "",
    "healthcare_fund_zipcode": "",
    "healthcare_fund_city": "",
    "healthcare_fund_state": "",
    "general_practitioner": "",
    "telephone_emergency": "",
    "contract_start": "",
    "contract_end": "",
    "contract_independent": false,
    "contract_type": "",
    "contract_type_localized": "",
    "classification": "",
    "employment_form": "",
    "employment_form_localized": "",
    "employment_status": "",
    "employment_status_localized": "",
    "personnel_nr": "",
    "dimona_nr": "",
    "drivers_license": false,
    "drivers_license_expire_date": "",
    "acknowledgement_nr_gv": "",
    "acknowledgement_nr_tv": "",
    "acknowledgement_nr_va": "",
    "acknowledgement_nr_sv": "",
    "acknowledgement_g1": false,
    "acknowledgement_g2": false,
    "acknowledgement_l": false,
    "distance_commute": 0,
    "active": true,
    "ts_lastupdate": "2025–02–12 14:28:02"
  }
]
}

/Employees/{id}/image

If everything succeeds the HTTP response status is 200
(200 OK)

If there is something wrong with the request, the response status and code is 400
(400 Bad Request)

If there is no record that has the requested id the HTTP response status and code is 404
(404 Not found)

If you forget to send the Authorization, the response status is 401
(401 Unauthorized)

If what you sent can’t be processed, the response status is 500
(500 Internal Server Error)

For an explanation of all possible errors, please consult our section on possible answers to API calls here

Examples:

https://ra.bouwsoft.be/api/v1/Employees/164/image

with the following parameters :

Header Parameters :
ParameterName: Clientnr, ParameterValue: 115
ParameterName: AccessToken, ParameterValue: jGkfWxfVlGzSfGbrDfzRqOrUfPmAGfVAfmAbzGjjlAAfAAbbAm

Success gives statuscode 200 And the following result

image

/Employees/{id}/note_html

If everything succeeds the HTTP response status is 200
(200 OK)

If there is something wrong with the request, the response status and code is 400
(400 Bad Request)

If there is no record that has the requested id the HTTP response status and code is 404
(404 Not found)

If you forget to send the Authorization, the response status is 401
(401 Unauthorized)

If what you sent can’t be processed, the response status is 500
(500 Internal Server Error)

For an explanation of all possible errors, please consult our section on possible answers to API calls here

Examples:

https://ra.bouwsoft.be/api/v1/Employees/164/note_html

with the following parameters :

Header Parameters :
ParameterName: Clientnr, ParameterValue: 115
ParameterName: AccessToken, ParameterValue: VOtfWxfIVIzSfPPfUfzRqjOVfAtbkGAVfIfkzIjmjPIIDDUVAt

Success gives statuscode 200 And the following result

<HTML><BODY> <DIV STYLE="text-align: left;"><SPAN STYLE="font-family: Arial;font-size: 12pt;color: #000000;">I'm an old person. It's the sort of thing that happens when you aren't looking. All the kids these days are writing Slack and Discord bots in JavaScript, and I remember writing my first chatbots in Perl and hooking them into IRC. Fortunately, all the WTFs in my Perl chatbots have been lost to time.<BR> <BR> <B>"P"</B> has a peer who wants to scrape all the image URLs out of a Discord chat channel. Those URLs will be fetched, then passed through an image processing pipeline to organize and catalog frequently used images, regardless of their origin.<BR> <BR> Our intrepid scraper, however, doesn't want to run the risk of trying to request a URL that might be invalid. So they need a way to accurately validate every URL.<BR> <BR> Now, the trick to URLs, and URIs in general, is that they have a grammar that seems simple but is deceptively complex and doesn't lend itself to precise validation via regular expressions. If you were a sane person, you'd generally just ballpark it into the neighborhood and handle exceptions, or maybe <U>copy/paste from StackOverflow</U> and call it a day.<BR> <BR> This developer spent 7 hours developing their own regular expression to validate a URL. They tested it with every URL they could think of, and it passed with 100% accuracy, which sounds like the kind of robust testing we'd expect from the person who wrote this:<BR> <BR> </SPAN><SPAN STYLE="font-family: Arial;font-size: 12pt;color: #008888;">&nbsp;&nbsp;<B></SPAN><SPAN STYLE="font-family: Arial;font-size: 12pt;color: #000000;">const</B> regex =</SPAN><SPAN STYLE="font-family: Arial;font-size: 12pt;color: #008888;"> /((?:(http|https|Http|Https|rtsp|Rtsp):\/\/(?:(?:<BR> &nbsp;&nbsp;[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&amp;\=]|(?:\%[a-fA-F0-9]{2})){1,64}(?:\:<BR> &nbsp;&nbsp;(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&amp;\=]|(?:\%[a-fA-F0-9]{2})){1,25})?<BR> &nbsp;&nbsp;<A href="mailto:\@)?)?((?:(?:[a-zA-Z0-9][a-zA-Z0-9\-]{0,64}\.)+(?:(?:aero|arpa|asia|a">\@)?)?((?:(?:[a-zA-Z0-9][a-zA-Z0-9\-]{0,64}\.)+(?:(?:aero|arpa|asia|a</A><BR> &nbsp;&nbsp;[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c<BR> &nbsp;&nbsp;[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g<BR> &nbsp;&nbsp;[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop]<BR> &nbsp;&nbsp;)|k[eghimnrwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])<BR> &nbsp;&nbsp;|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r<BR> &nbsp;&nbsp;[eouw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u<BR> &nbsp;&nbsp;[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw]))|(?:(?:25[0-5]|2[0-4][0-9]|[0-1]<BR> &nbsp;&nbsp;[0-9]{2}|[1-9][0-9]|[1-9])\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]<BR> &nbsp;&nbsp;|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25<BR> &nbsp;&nbsp;[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])))(?:\:\d{1,5})?)(\/(?:(?:<BR> &nbsp;&nbsp;<A href="mailto:[a-zA-Z0-9\;\/\?\:\@\&\=\#\~\-\.\+\!\*\'\(\)\,\_])|(?:\%[a-fA-F0-9]{2}))*)?">[a-zA-Z0-9\;\/\?\:\@\&amp;\=\#\~\-\.\+\!\*\'\(\)\,\_])|(?:\%[a-fA-F0-9]{2}))*)?</A><BR> &nbsp;&nbsp;(?:\b|$)/gi<BR> <BR> </SPAN><SPAN STYLE="font-family: Arial;font-size: 12pt;color: #000000;">Note each use of (?:). These are "look ahead" matches, which will execute depending on what comes after them. Using one or two of these in a regex makes its massively more complicated. This regex uses 32 look ahead expressions, taking "unreadability" to a new height, and flirting with the lesser demons which serve <U>Zalgo.</U> Bonus points for making the comparison case insensitive, but also checking for both http and Http, just in case.<BR> <BR> "There's no module on NPM that can do all of this!" the developer proudly proclaimed. They then presumably uploaded it to NPM as a "microframework", used it within a few of their own modules, and then those modules got used by some other modules, and now 75% of the web depends on this regex.</SPAN></DIV> </BODY></HTML>

/Employees/{id}/note_plain

If everything succeeds the HTTP response status is 200
(200 OK)

If there is something wrong with the request, the response status and code is 400
(400 Bad Request)

If there is no record that has the requested id the HTTP response status and code is 404
(404 Not found)

If you forget to send the Authorization, the response status is 401
(401 Unauthorized)

If what you sent can’t be processed, the response status is 500
(500 Internal Server Error)

For an explanation of all possible errors, please consult our section on possible answers to API calls here

Examples:

https://ra.bouwsoft.be/api/v1/Employees/164/note_plain

with the following parameters :

Header Parameters :
ParameterName: Clientnr, ParameterValue: 115
ParameterName: AccessToken, ParameterValue: ftAfWxffjbzSfVIDrfzRqVrbfGUrGfVDfDbbzbIrtbOffrmlVO

Success gives statuscode 200 And the following result

I’m an old person. It’s the sort of thing that happens when you aren’t looking. All the kids these days are writing Slack and Discord bots in JavaScript, and I remember writing my first chatbots in Perl and hooking them into IRC. Fortunately, all the WTFs in my Perl chatbots have been lost to time.

“P” has a peer who wants to scrape all the image URLs out of a Discord chat channel. Those URLs will be fetched, then passed through an image processing pipeline to organize and catalog frequently used images, regardless of their origin.

Our intrepid scraper, however, doesn’t want to run the risk of trying to request a URL that might be invalid. So they need a way to accurately validate every URL.

Now, the trick to URLs, and URIs in general, is that they have a grammar that seems simple but is deceptively complex and doesn’t lend itself to precise validation via regular expressions. If you were a sane person, you’d generally just ballpark it into the neighborhood and handle exceptions, or maybe copy/paste from StackOverflow and call it a day.

This developer spent 7 hours developing their own regular expression to validate a URL. They tested it with every URL they could think of, and it passed with 100% accuracy, which sounds like the kind of robust testing we’d expect from the person who wrote this:

const regex = /((?:(http|https|Http|Https|rtsp|Rtsp):\/\/(?:(?: [a-zA-Z0–9$-_.+!*'()\,\;\?\&\=]|(?:\%[a-fA-F0–9]{2})){1,64}(?:\: (?:[a-zA-Z0–9$-_.+!*'()\,\;\?\&\=]|(?:\%[a-fA-F0–9]{2})){1,25})? \@)?)?((?:(?:[a-zA-Z0–9][a-zA-Z0-9-]{0,64}.)+(?:(?:aero|arpa|asia|a [cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c [acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g [abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop] )|k[eghimnrwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz]) |(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r [eouw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u [agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw]))|(?:(?:25[0–5]|2[0–4][0-9]|[0–1][0-9]{2}|[1–9][0-9]|[1–9]).(?:25[0–5]|2[0–4][0-9]|[0–1][0-9]{2}|[1–9][0-9] |[1–9]|0).(?:25[0–5]|2[0–4][0-9]|[0–1][0-9]{2}|[1–9][0-9]|[1–9]|0).(?:25 [0–5]|2[0–4][0-9]|[0–1][0-9]{2}|[1–9][0-9]|[0–9])))(?:\:\d{1,5})?)(\/(?:(?: [a-zA-Z0–9\;\/\?\:\@\&\=#~-.+!*'()\,_])|(?:\%[a-fA-F0–9]{2}))*)? (?:\b|$)/gi

Note each use of (?:). These are “look ahead” matches, which will execute depending on what comes after them. Using one or two of these in a regex makes its massively more complicated. This regex uses 32 look ahead expressions, taking “unreadability” to a new height, and flirting with the lesser demons which serve Zalgo. Bonus points for making the comparison case insensitive, but also checking for both http and Http, just in case.

“There’s no module on NPM that can do all of this!” the developer proudly proclaimed. They then presumably uploaded it to NPM as a “microframework”, used it within a few of their own modules, and then those modules got used by some other modules, and now 75% of the web depends on this regex.

/Employees/{id}/note_rtf

If everything succeeds the HTTP response status is 200
(200 OK)

If there is something wrong with the request, the response status and code is 400
(400 Bad Request)

If there is no record that has the requested id the HTTP response status and code is 404
(404 Not found)

If you forget to send the Authorization, the response status is 401
(401 Unauthorized)

If what you sent can’t be processed, the response status is 500
(500 Internal Server Error)

For an explanation of all possible errors, please consult our section on possible answers to API calls here

Examples:

https://ra.bouwsoft.be/api/v1/Employees/164/note_rtf

with the following parameters :

Header Parameters :
ParameterName: Clientnr, ParameterValue: 115
ParameterName: AccessToken, ParameterValue: UfDfWxfOPkzSftIAGfzRqVrrfVmOkGrbftAkzbPDAbPIkfDkUb

Success gives statuscode 200 And the following result

{\rtf1\ansi\deff0{\fonttbl{\f0\fnil Arial;}}{\colortbl ;\red0\green0\blue0;\red0\green136\blue136;}{*\generator Spikesoft 16.02;}\ql\li0\f0\fs24\cf1 I’m an old person. It’s the sort of thing that happens when you aren’t looking. All the kids these days are writing Slack and Discord bots in JavaScript, and I remember writing my first chatbots in Perl and hooking them into IRC. Fortunately, all the WTFs in my Perl chatbots have been lost to time.\par\par\b “P”\b0 has a peer who wants to scrape all the image URLs out of a Discord chat channel. Those URLs will be fetched, then passed through an image processing pipeline to organize and catalog frequently used images, regardless of their origin.\par\par Our intrepid scraper, however, doesn’t want to run the risk of trying to request a URL that might be invalid. So they need a way to accurately validate every URL.\par\par Now, the trick to URLs, and URIs in general, is that they have a grammar that seems simple but is deceptively complex and doesn’t lend itself to precise validation via regular expressions. If you were a sane person, you’d generally just ballpark it into the neighborhood and handle exceptions, or maybe \ul copy/paste from StackOverflow\ul0 and call it a day.\par\par This developer spent 7 hours developing their own regular expression to validate a URL. They tested it with every URL they could think of, and it passed with 100% accuracy, which sounds like the kind of robust testing we’d expect from the person who wrote this:\par\par\cf2 \cf1\b const\b0 regex =\cf2 /((?:(http|https|Http|Https|rtsp|Rtsp):\ /\ /(?:(?:\par [a-zA-Z0–9\ \(\\ -\\ _\\ .\\ +\\ !\\ *\\ '\\ (\\ )\\ ,\\ ;\\ ?\\ &\\ =]|(?:\\ %[a-fA-F0-9]\{ 2\} ))\{ 1,64\} (?:\\ :\par (?:[a-zA-Z0-9\\ $\\ -\\ _\\ .\\ +\\ !\\ *\\ '\\ (\\ )\\ ,\\ ;\\ ?\\ &\\ =]|(?:\\ %[a-fA-F0-9]\{ 2\} ))\{ 1,25\} )?\par \\ @)?)?((?:(?:[a-zA-Z0-9][a-zA-Z0-9\\ -]\{ 0,64\}\\ .)+(?:(?:aero|arpa|asia|a\par [cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c\par [acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g\par [abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop]\par )|k[eghimnrwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])\par |(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r\par [eouw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u\par [agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw]))|(?:(?:25[0-5]|2[0-4][0-9]|[0-1]\par [0-9]\{ 2\} |[1-9][0-9]|[1-9])\\ .(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]\{ 2\} |[1-9][0-9]\par |[1-9]|0)\\ .(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]\{ 2\} |[1-9][0-9]|[1-9]|0)\\ .(?:25\par [0-5]|2[0-4][0-9]|[0-1][0-9]\{ 2\} |[1-9][0-9]|[0-9])))(?:\\ :\\ d\{ 1,5\} )?)(\\ /(?:(?:\par [a-zA-Z0-9\\ ;\\ /\\ ?\\ :\\ @\\ &\\ =\\ #\\ ~\\ -\\ .\\ +\\ !\\ *\\ '\\ (\\ )\\ ,\\ _])|(?:\\ %[a-fA-F0-9]\{ 2\} ))*)?\par (?:\\ b|\))/gi\par\par\cf1 Note each use of (?:). These are “look ahead” matches, which will execute depending on what comes after them. Using one or two of these in a regex makes its massively more complicated. This regex uses 32 look ahead expressions, taking “unreadability” to a new height, and flirting with the lesser demons which serve \ul Zalgo.\ul0 Bonus points for making the comparison case insensitive, but also checking for both http and Http, just in case.\par\par “There’s no module on NPM that can do all of this!” the developer proudly proclaimed. They then presumably uploaded it to NPM as a “microframework”, used it within a few of their own modules, and then those modules got used by some other modules, and now 75% of the web depends on this regex.}